In-Browser CSV Parsers

JavaScript performance comparison

Revision 7 of this test case created by Rob

Preparation code

<!-- jQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

<!-- CSV libraries -->
<script src="http://jquery-csv.googlecode.com/git/src/jquery.csv.js"></script>
<script src="https://rawgit.com/henix/csv.js/master/csv.js"></script>
<script>var henixCsv = CSV; // avoid namespace collision</script>
<script src="https://rawgit.com/knrz/CSV.js/master/csv.min.js"></script>
<script src="https://rawgit.com/mholt/PapaParse/master/papaparse.min.js"></script>
<script>
// Papa Parse 3.1 version of the parser
function Papa3Parser(e){function y(){while(f<n.length){if(g)break;if(u>0&&m>=u)break;if(a=='"')E();else if(l)S();else x();b()}return w()}function b(){f++;a=n[f]}function w(){if(g)B("Abort","ParseAbort","Parsing was aborted by the user's step function");if(l)B("Quotes","MissingQuotes","Unescaped or mismatched quotes");A();if(!q(s))return I()}function E(){if(P()&&!D())l=!l;else{C();if(l&&D())f++;else B("Quotes","UnexpectedQuotes","Unexpected quotes")}}function S(){if(M(f)||_(f))c++;C()}function x(){if(a==r)k();else if(M(f)){L();b()}else if(_(f))L();else if(T())N();else C()}function T(){if(!i)return false;var e=f==0||_(f-1)||M(f-2);return e&&n[f]===i}function N(){while(!M(f)&&!_(f)&&f<n.length){b()}}function C(){h[d][v]+=a}function k(){h[d].push("");v=h[d].length-1}function L(){A();c++;m++;h.push([]);d=h.length-1;k()}function A(){O();if(q(s)){if(h[d])s(I());F()}}function O(){if(h[d].length==1&&t.test(h[d][0])){if(e.keepEmptyRows)h[d].splice(0,1);else h.splice(d,1);d=h.length-1}}function M(e){return e<n.length-1&&(n[e]=="\r"&&n[e+1]=="\n"||n[e]=="\n"&&n[e+1]=="\r")}function _(e){return n[e]=="\r"||n[e]=="\n"}function D(){return!P()&&f<n.length-1&&n[f+1]=='"'}function P(){return!l&&H(f-1)||H(f+1)}function H(e){if(typeof e!="number")e=f;var t=n[e];return e<=-1||e>=n.length||t==r||t=="\r"||t=="\n"}function B(e,t,n){p.push({type:e,code:t,message:n,line:c,row:d,index:f})}function j(e){n=e;l=false;f=0,m=0,c=1;F();h=[[""]];a=n[f]}function F(){h=[];p=[];d=0;v=0}function I(){return{data:h,errors:p,meta:{lines:c,delimiter:r,aborted:g,truncated:u>0&&f<n.length}}}function q(e){return typeof e==="function"}var t=/^\s*$/;var n;var r;var i;var s;var o;var u;var a;var f;var l;var c;var h;var p;var d;var v;var m;var g=false;e=e||{};r=e.delimiter;i=e.comments;s=e.step;u=e.preview;if(typeof r!=="string"||r.length!=1)r=",";if(i===true)i="#";else if(typeof i!=="string"||i.length!=1||i==r)i=false;this.parse=function(e){if(typeof e!=="string")throw"Input must be a string";j(e);return y()};this.abort=function(){g=true};this.getCharIndex=function(){return f}};
</script>

<!-- CSV strings to parse -->
<script>
var csvString = "Hello,421,,Hello\\,world,\\N,Sadness\\N";



var csvStringSimple = "Hello,421,,Hello\\,world,\\N,Sadness\\N";
</script>

<!-- Prepare the parsers -->
<script>
var papa = new Papa.Parser();
var fastPapa = new Papa.Parser({ fastMode: true });
var oldPapa = new Papa3Parser();
var knrzCsv = new CSV(csvString);
</script>
      
<script>
Benchmark.prototype.setup = function() {
  function DMparse(line) {
      var elem = [''];
      var elemCount = 0;
      var charCount = 0;
      for (x = 0; x < line.length; x++) {
          if (line[x] == ',' && line[x - 1] != '\\') {
              elemCount++;
              elem[elemCount] = '';
              charCount = 0;
          } else if (charCount == 0 && line[x] == '\\' && line[x + 1] == 'N' && (line[x + 2] == ',' || (x + 2) >= line.length)) {
              x = x + 2;
              if (x < line.length) {
                  elemCount++;
                  elem[elemCount] = '';
              }
          } else {
              if (line[x] == ',') {
                  elem[elemCount] = elem[elemCount].substr(0, elem[elemCount].length - 1) + ',';
              } else {
                  elem[elemCount] = elem[elemCount] + line[x];
                  charCount++;
              }
          }
      }
      return elem;
  }

};
</script>

Preparation code output

<!-- jQuery --> <!-- CSV libraries --> <script src="http://jquery-csv.googlecode.com/git/src/jquery.csv.js"></script> <script src="https://rawgit.com/henix/csv.js/master/csv.js"></script> <script>var henixCsv = CSV; // avoid namespace collision</script> <script src="https://rawgit.com/knrz/CSV.js/master/csv.min.js"></script> <script src="https://rawgit.com/mholt/PapaParse/master/papaparse.min.js"></script> <script> // Papa Parse 3.1 version of the parser function Papa3Parser(e){function y(){while(f<n.length){if(g)break;if(u>0&&m>=u)break;if(a=='"')E();else if(l)S();else x();b()}return w()}function b(){f++;a=n[f]}function w(){if(g)B("Abort","ParseAbort","Parsing was aborted by the user's step function");if(l)B("Quotes","MissingQuotes","Unescaped or mismatched quotes");A();if(!q(s))return I()}function E(){if(P()&&!D())l=!l;else{C();if(l&&D())f++;else B("Quotes","UnexpectedQuotes","Unexpected quotes")}}function S(){if(M(f)||_(f))c++;C()}function x(){if(a==r)k();else if(M(f)){L();b()}else if(_(f))L();else if(T())N();else C()}function T(){if(!i)return false;var e=f==0||_(f-1)||M(f-2);return e&&n[f]===i}function N(){while(!M(f)&&!_(f)&&f<n.length){b()}}function C(){h[d][v]+=a}function k(){h[d].push("");v=h[d].length-1}function L(){A();c++;m++;h.push([]);d=h.length-1;k()}function A(){O();if(q(s)){if(h[d])s(I());F()}}function O(){if(h[d].length==1&&t.test(h[d][0])){if(e.keepEmptyRows)h[d].splice(0,1);else h.splice(d,1);d=h.length-1}}function M(e){return e<n.length-1&&(n[e]=="\r"&&n[e+1]=="\n"||n[e]=="\n"&&n[e+1]=="\r")}function _(e){return n[e]=="\r"||n[e]=="\n"}function D(){return!P()&&f<n.length-1&&n[f+1]=='"'}function P(){return!l&&H(f-1)||H(f+1)}function H(e){if(typeof e!="number")e=f;var t=n[e];return e<=-1||e>=n.length||t==r||t=="\r"||t=="\n"}function B(e,t,n){p.push({type:e,code:t,message:n,line:c,row:d,index:f})}function j(e){n=e;l=false;f=0,m=0,c=1;F();h=[[""]];a=n[f]}function F(){h=[];p=[];d=0;v=0}function I(){return{data:h,errors:p,meta:{lines:c,delimiter:r,aborted:g,truncated:u>0&&f<n.length}}}function q(e){return typeof e==="function"}var t=/^\s*$/;var n;var r;var i;var s;var o;var u;var a;var f;var l;var c;var h;var p;var d;var v;var m;var g=false;e=e||{};r=e.delimiter;i=e.comments;s=e.step;u=e.preview;if(typeof r!=="string"||r.length!=1)r=",";if(i===true)i="#";else if(typeof i!=="string"||i.length!=1||i==r)i=false;this.parse=function(e){if(typeof e!=="string")throw"Input must be a string";j(e);return y()};this.abort=function(){g=true};this.getCharIndex=function(){return f}}; </script> <!-- CSV strings to parse --> <script> var csvString = "Hello,421,,Hello\\,world,\\N,Sadness\\N"; var csvStringSimple = "Hello,421,,Hello\\,world,\\N,Sadness\\N"; </script> <!-- Prepare the parsers --> <script> var papa = new Papa.Parser(); var fastPapa = new Papa.Parser({ fastMode: true }); var oldPapa = new Papa3Parser(); var knrzCsv = new CSV(csvString); </script>

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in CCBot 2.0.0 / Other 0.0.0
Test Ops/sec
jquery-csv
jQuery.csv.toArrays(csvString);
pending…
knrz/CSV.js
knrzCsv.parse();
pending…
henix/csv.js
henixCsv.parse(csvString);
pending…
Old Papa Parse (3.1)
oldPapa.parse(csvString);
pending…
Papa Parse
papa.parse(csvString);
pending…
henix/csv.js (no quoted fields)
henixCsv.parse(csvStringSimple);
pending…
Papa Parse (fast mode, no quoted fields)
fastPapa.parse(csvStringSimple);
pending…
DMparse
DMparse(csvString)
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL.

0 Comments