diff --git a/bits/01_version.js b/bits/01_version.js index 7057794..426934a 100644 --- a/bits/01_version.js +++ b/bits/01_version.js @@ -1 +1 @@ -CRC32.version = '0.2.0'; +CRC32.version = '0.2.1'; diff --git a/bits/40_crc.js b/bits/40_crc.js index 40e3593..d378abc 100644 --- a/bits/40_crc.js +++ b/bits/40_crc.js @@ -1,7 +1,7 @@ /* charCodeAt is the best approach for binary strings */ var use_buffer = typeof Buffer !== 'undefined'; function crc32_bstr(bstr) { - if(bstr.length > 32768) if(use_buffer) return crc32_buf(Buffer(bstr)); + if(bstr.length > 32768) if(use_buffer) return crc32_buf_8(Buffer(bstr)); var crc = -1, L = bstr.length - 1; for(var i = 0; i < L;) { crc = table[(crc ^ bstr.charCodeAt(i++)) & 0xFF] ^ (crc >>> 8); @@ -12,18 +12,29 @@ function crc32_bstr(bstr) { } function crc32_buf(buf) { + if(buf.length > 10000) return crc32_buf_8(buf); for(var crc = -1, i = 0, L=buf.length-3; i < L;) { crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; } - if(i < L+3) { + while(i < L+3) crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; + return crc ^ -1; +} + +function crc32_buf_8(buf) { + for(var crc = -1, i = 0, L=buf.length-7; i < L;) { crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; - if(i < L+3) { - crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; - if(i < L+3) { - crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; }}} + crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; + crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; + crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; + crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; + crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; + crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; + crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; + } + while(i < L+7) crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; return crc ^ -1; } diff --git a/crc32.js b/crc32.js index 37a1186..d3651d3 100644 --- a/crc32.js +++ b/crc32.js @@ -2,7 +2,7 @@ /* vim: set ts=2: */ var CRC32 = {}; (function(CRC32) { -CRC32.version = '0.2.0'; +CRC32.version = '0.2.1'; /* see perf/crc32table.js */ function signed_crc_table() { var c, table = new Array(256); @@ -27,7 +27,7 @@ var table = signed_crc_table(); /* charCodeAt is the best approach for binary strings */ var use_buffer = typeof Buffer !== 'undefined'; function crc32_bstr(bstr) { - if(bstr.length > 32768) if(use_buffer) return crc32_buf(Buffer(bstr)); + if(bstr.length > 32768) if(use_buffer) return crc32_buf_8(Buffer(bstr)); var crc = -1, L = bstr.length - 1; for(var i = 0; i < L;) { crc = table[(crc ^ bstr.charCodeAt(i++)) & 0xFF] ^ (crc >>> 8); @@ -38,18 +38,29 @@ function crc32_bstr(bstr) { } function crc32_buf(buf) { + if(buf.length > 10000) return crc32_buf_8(buf); for(var crc = -1, i = 0, L=buf.length-3; i < L;) { crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; } - if(i < L+3) { + while(i < L+3) crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; + return crc ^ -1; +} + +function crc32_buf_8(buf) { + for(var crc = -1, i = 0, L=buf.length-7; i < L;) { crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; - if(i < L+3) { - crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; - if(i < L+3) { - crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; }}} + crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; + crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; + crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; + crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; + crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; + crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; + crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; + } + while(i < L+7) crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; return crc ^ -1; } diff --git a/ctest/crc32.js b/ctest/crc32.js index 37a1186..d3651d3 100644 --- a/ctest/crc32.js +++ b/ctest/crc32.js @@ -2,7 +2,7 @@ /* vim: set ts=2: */ var CRC32 = {}; (function(CRC32) { -CRC32.version = '0.2.0'; +CRC32.version = '0.2.1'; /* see perf/crc32table.js */ function signed_crc_table() { var c, table = new Array(256); @@ -27,7 +27,7 @@ var table = signed_crc_table(); /* charCodeAt is the best approach for binary strings */ var use_buffer = typeof Buffer !== 'undefined'; function crc32_bstr(bstr) { - if(bstr.length > 32768) if(use_buffer) return crc32_buf(Buffer(bstr)); + if(bstr.length > 32768) if(use_buffer) return crc32_buf_8(Buffer(bstr)); var crc = -1, L = bstr.length - 1; for(var i = 0; i < L;) { crc = table[(crc ^ bstr.charCodeAt(i++)) & 0xFF] ^ (crc >>> 8); @@ -38,18 +38,29 @@ function crc32_bstr(bstr) { } function crc32_buf(buf) { + if(buf.length > 10000) return crc32_buf_8(buf); for(var crc = -1, i = 0, L=buf.length-3; i < L;) { crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; } - if(i < L+3) { + while(i < L+3) crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; + return crc ^ -1; +} + +function crc32_buf_8(buf) { + for(var crc = -1, i = 0, L=buf.length-7; i < L;) { crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; - if(i < L+3) { - crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; - if(i < L+3) { - crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; }}} + crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; + crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; + crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; + crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; + crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; + crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; + crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; + } + while(i < L+7) crc = (crc >>> 8) ^ table[(crc^buf[i++])&0xFF]; return crc ^ -1; } diff --git a/ctest/fixtures.js b/ctest/fixtures.js index 58a6e0a..faffab9 100644 --- a/ctest/fixtures.js +++ b/ctest/fixtures.js @@ -6,8 +6,10 @@ var bits = [ [ "foo bar baz٪☃🍣", 1531648243] ]; if(typeof module !== "undefined") module.exports = bits; +/* vim: set ts=2: */ if(typeof require !== 'undefined') { var js_crc32 = require('../'); +var js_crc32_old = require('crc-32'); var buffer_crc32 = require('./buffer-crc32'); var crc32 = require('./crc32'); var node_crc = require('./node-crc'); @@ -16,16 +18,19 @@ function z1(bstr) { return js_crc32.bstr(bstr); } function z2(bstr) { return buffer_crc32.signed(bstr); } function z3(bstr) { return crc32(bstr); } function z4(bstr) { return node_crc.crc32(bstr);} +function z5(bstr) { return js_crc32_old.bstr(bstr); } function b1(buf) { return js_crc32.buf(buf); } function b2(buf) { return buffer_crc32.signed(buf); } function b3(buf) { return crc32(buf); } function b4(buf) { return node_crc.crc32(buf); } +function b5(buf) { return js_crc32_old.buf(buf); } function u1(str) { return js_crc32.str(str); } function u2(str) { return buffer_crc32.signed(str); } +function u3(str) { return js_crc32_old.str(str); } -var ntests, len_max; +var ntests, len_max, do_bstr, do_buf, do_ustr; switch(process.env.MODE) { case "A": ntests = 100000; len_max = 256; break; case "B": ntests = 10000; len_max = 1024; break; @@ -36,7 +41,15 @@ switch(process.env.MODE) { default: ntests = 10000; len_max = 1024; break; } -var btest = true, utest = true; +if(process.argv === 2) do_bstr = do_buf = do_ustr = true; +else { + do_bstr = process.argv[2].indexOf("S") > -1; + do_buf = process.argv[2].indexOf("B") > -1; + do_ustr = process.argv[2].indexOf("U") > -1; + if(!do_bstr && !do_buf && !do_ustr) do_bstr = do_buf = do_ustr = true; +} + +var btest = !!do_bstr || !!do_buf, utest = !!do_ustr; var bstr_tests = []; var ustr_tests = []; @@ -60,44 +73,61 @@ for(var i = 0; i < ntests; ++i) { var assert = require('assert'); function fix(str) { return parseInt(str, 16)|0; } if(btest) for(var j = 0; j != ntests; ++j) { - assert.equal(z1(bstr_tests[j][0]), b1(bstr_tests[j][1])); + if(do_bstr && do_buf) assert.equal(z1(bstr_tests[j][0]), b1(bstr_tests[j][1])); - assert.equal(z1(bstr_tests[j][0]), z2(bstr_tests[j][0])); - assert.equal(z1(bstr_tests[j][0]), fix(z3(bstr_tests[j][0]))); - assert.equal(z1(bstr_tests[j][0]), fix(z4(bstr_tests[j][0]))); + if(do_bstr) { + assert.equal(z1(bstr_tests[j][0]), z2(bstr_tests[j][0])); + assert.equal(z1(bstr_tests[j][0]), fix(z3(bstr_tests[j][0]))); + assert.equal(z1(bstr_tests[j][0]), fix(z4(bstr_tests[j][0]))); + assert.equal(z1(bstr_tests[j][0]), z5(bstr_tests[j][0])); + } - assert.equal(b1(bstr_tests[j][1]), b2(bstr_tests[j][1])); - assert.equal(b1(bstr_tests[j][1]), fix(b3(bstr_tests[j][1]))); - assert.equal(b1(bstr_tests[j][1]), fix(b4(bstr_tests[j][1]))); + if(do_buf) { + assert.equal(b1(bstr_tests[j][1]), b2(bstr_tests[j][1])); + assert.equal(b1(bstr_tests[j][1]), fix(b3(bstr_tests[j][1]))); + assert.equal(b1(bstr_tests[j][1]), fix(b4(bstr_tests[j][1]))); + assert.equal(b1(bstr_tests[j][1]), b5(bstr_tests[j][1])); + } } if(utest) for(var j = 0; j != ntests; ++j) { assert.equal(u1(ustr_tests[j]), u2(ustr_tests[j])); + assert.equal(u1(ustr_tests[j]), u3(ustr_tests[j])); } var BM = require('../perf/bm'); + +if(do_bstr) { var suite = new BM('binary string (' + len_max + ')'); suite.add('js-crc32', function() { for(var j = 0; j != ntests; ++j) z1(bstr_tests[j][0]); }); +suite.add('js-crc32-old', function() { for(var j = 0; j != ntests; ++j) z5(bstr_tests[j][0]); }); suite.add('buffer-crc32', function() { for(var j = 0; j != ntests; ++j) z2(bstr_tests[j][0]); }); if(len_max < 4096) { suite.add('crc32', function() { for(var j = 0; j != ntests; ++j) z3(bstr_tests[j][0]); }); suite.add('node_crc', function() { for(var j = 0; j != ntests; ++j) z4(bstr_tests[j][0]); }); } suite.run(); +} +if(do_buf) { suite = new BM('buffer (' + len_max + ')'); suite.add('js-crc32', function() { for(var j = 0; j != ntests; ++j) b1(bstr_tests[j][1]); }); +suite.add('js-crc32-old', function() { for(var j = 0; j != ntests; ++j) b5(bstr_tests[j][1]); }); suite.add('buffer-crc32', function() { for(var j = 0; j != ntests; ++j) b2(bstr_tests[j][1]); }); if(len_max < 1024) { suite.add('crc32', function() { for(var j = 0; j != ntests; ++j) b3(bstr_tests[j][1]); }); suite.add('node_crc', function() { for(var j = 0; j != ntests; ++j) b4(bstr_tests[j][1]); }); } suite.run(); +} +if(do_ustr) { var suite = new BM('unicode string (' + len_max + ')'); suite.add('js-crc32', function() { for(var j = 0; j != ntests; ++j) u1(ustr_tests[j]); }); +suite.add('js-crc32-old', function() { for(var j = 0; j != ntests; ++j) u3(ustr_tests[j]); }); suite.add('buffer-crc32', function() { for(var j = 0; j != ntests; ++j) u2(ustr_tests[j]); }); suite.run(); } +} crc32table = [ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, diff --git a/misc/integration.js b/misc/integration.js index 22b59b7..f71e727 100644 --- a/misc/integration.js +++ b/misc/integration.js @@ -1,5 +1,7 @@ +/* vim: set ts=2: */ if(typeof require !== 'undefined') { var js_crc32 = require('../'); +var js_crc32_old = require('crc-32'); var buffer_crc32 = require('./buffer-crc32'); var crc32 = require('./crc32'); var node_crc = require('./node-crc'); @@ -8,16 +10,19 @@ function z1(bstr) { return js_crc32.bstr(bstr); } function z2(bstr) { return buffer_crc32.signed(bstr); } function z3(bstr) { return crc32(bstr); } function z4(bstr) { return node_crc.crc32(bstr);} +function z5(bstr) { return js_crc32_old.bstr(bstr); } function b1(buf) { return js_crc32.buf(buf); } function b2(buf) { return buffer_crc32.signed(buf); } function b3(buf) { return crc32(buf); } function b4(buf) { return node_crc.crc32(buf); } +function b5(buf) { return js_crc32_old.buf(buf); } function u1(str) { return js_crc32.str(str); } function u2(str) { return buffer_crc32.signed(str); } +function u3(str) { return js_crc32_old.str(str); } -var ntests, len_max; +var ntests, len_max, do_bstr, do_buf, do_ustr; switch(process.env.MODE) { case "A": ntests = 100000; len_max = 256; break; case "B": ntests = 10000; len_max = 1024; break; @@ -28,7 +33,15 @@ switch(process.env.MODE) { default: ntests = 10000; len_max = 1024; break; } -var btest = true, utest = true; +if(process.argv === 2) do_bstr = do_buf = do_ustr = true; +else { + do_bstr = process.argv[2].indexOf("S") > -1; + do_buf = process.argv[2].indexOf("B") > -1; + do_ustr = process.argv[2].indexOf("U") > -1; + if(!do_bstr && !do_buf && !do_ustr) do_bstr = do_buf = do_ustr = true; +} + +var btest = !!do_bstr || !!do_buf, utest = !!do_ustr; var bstr_tests = []; var ustr_tests = []; @@ -52,41 +65,58 @@ for(var i = 0; i < ntests; ++i) { var assert = require('assert'); function fix(str) { return parseInt(str, 16)|0; } if(btest) for(var j = 0; j != ntests; ++j) { - assert.equal(z1(bstr_tests[j][0]), b1(bstr_tests[j][1])); + if(do_bstr && do_buf) assert.equal(z1(bstr_tests[j][0]), b1(bstr_tests[j][1])); - assert.equal(z1(bstr_tests[j][0]), z2(bstr_tests[j][0])); - assert.equal(z1(bstr_tests[j][0]), fix(z3(bstr_tests[j][0]))); - assert.equal(z1(bstr_tests[j][0]), fix(z4(bstr_tests[j][0]))); + if(do_bstr) { + assert.equal(z1(bstr_tests[j][0]), z2(bstr_tests[j][0])); + assert.equal(z1(bstr_tests[j][0]), fix(z3(bstr_tests[j][0]))); + assert.equal(z1(bstr_tests[j][0]), fix(z4(bstr_tests[j][0]))); + assert.equal(z1(bstr_tests[j][0]), z5(bstr_tests[j][0])); + } - assert.equal(b1(bstr_tests[j][1]), b2(bstr_tests[j][1])); - assert.equal(b1(bstr_tests[j][1]), fix(b3(bstr_tests[j][1]))); - assert.equal(b1(bstr_tests[j][1]), fix(b4(bstr_tests[j][1]))); + if(do_buf) { + assert.equal(b1(bstr_tests[j][1]), b2(bstr_tests[j][1])); + assert.equal(b1(bstr_tests[j][1]), fix(b3(bstr_tests[j][1]))); + assert.equal(b1(bstr_tests[j][1]), fix(b4(bstr_tests[j][1]))); + assert.equal(b1(bstr_tests[j][1]), b5(bstr_tests[j][1])); + } } if(utest) for(var j = 0; j != ntests; ++j) { assert.equal(u1(ustr_tests[j]), u2(ustr_tests[j])); + assert.equal(u1(ustr_tests[j]), u3(ustr_tests[j])); } var BM = require('../perf/bm'); + +if(do_bstr) { var suite = new BM('binary string (' + len_max + ')'); suite.add('js-crc32', function() { for(var j = 0; j != ntests; ++j) z1(bstr_tests[j][0]); }); +suite.add('js-crc32-old', function() { for(var j = 0; j != ntests; ++j) z5(bstr_tests[j][0]); }); suite.add('buffer-crc32', function() { for(var j = 0; j != ntests; ++j) z2(bstr_tests[j][0]); }); if(len_max < 4096) { suite.add('crc32', function() { for(var j = 0; j != ntests; ++j) z3(bstr_tests[j][0]); }); suite.add('node_crc', function() { for(var j = 0; j != ntests; ++j) z4(bstr_tests[j][0]); }); } suite.run(); +} +if(do_buf) { suite = new BM('buffer (' + len_max + ')'); suite.add('js-crc32', function() { for(var j = 0; j != ntests; ++j) b1(bstr_tests[j][1]); }); +suite.add('js-crc32-old', function() { for(var j = 0; j != ntests; ++j) b5(bstr_tests[j][1]); }); suite.add('buffer-crc32', function() { for(var j = 0; j != ntests; ++j) b2(bstr_tests[j][1]); }); if(len_max < 1024) { suite.add('crc32', function() { for(var j = 0; j != ntests; ++j) b3(bstr_tests[j][1]); }); suite.add('node_crc', function() { for(var j = 0; j != ntests; ++j) b4(bstr_tests[j][1]); }); } suite.run(); +} +if(do_ustr) { var suite = new BM('unicode string (' + len_max + ')'); suite.add('js-crc32', function() { for(var j = 0; j != ntests; ++j) u1(ustr_tests[j]); }); +suite.add('js-crc32-old', function() { for(var j = 0; j != ntests; ++j) u3(ustr_tests[j]); }); suite.add('buffer-crc32', function() { for(var j = 0; j != ntests; ++j) u2(ustr_tests[j]); }); suite.run(); } +} diff --git a/misc/perf.sh b/misc/perf.sh index 357935c..f197b35 100755 --- a/misc/perf.sh +++ b/misc/perf.sh @@ -10,9 +10,9 @@ git_module() { } echo "::: downloading modules" +npm install crc-32 2>/dev/null git_module node-crc https://github.com/alexgorbatchev/node-crc 2>/dev/null # crc git_module crc32 https://github.com/beatgammit/crc32 2>/dev/null # crc32 git_module buffer-crc32 https://github.com/brianloveswords/buffer-crc32 2>/dev/null # buffer-crc32 -for i in A B C D E F; do MODE="$i" node integration.js; done -# for i in E F; do MODE="$i" node integration.js; done +for i in A B C D E F; do MODE="$i" node integration.js "$1"; done diff --git a/package.json b/package.json index b547bc5..38f9af2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "crc-32", - "version": "0.2.0", + "version": "0.2.1", "author": "sheetjs", "description": "Pure-JS CRC-32", "keywords": [ "crc32", "checksum", "crc" ], diff --git a/perf/bm.js b/perf/bm.js index a742008..4dbebc5 100644 --- a/perf/bm.js +++ b/perf/bm.js @@ -2,7 +2,7 @@ var Benchmark = require('benchmark'); var c = require('ansi')(process.stdout); -function test_end() { c.horizontalAbsolute(0).write("✓"); c.write('\n'); } +function test_end(e) { c.horizontalAbsolute(0).write("✓ "+e.target); c.write('\n'); } function suite_end() { console.log('Fastest is ' + this.filter('fastest').pluck('name')); } @@ -16,7 +16,8 @@ function BM(name) { this.maxlen = 0; } -BM.prototype.run = function() { +BM.prototype.run = function(skip) { + if(skip) { this.suites.forEach(function(s) { s[1].fn(); }); return; } var maxlen = this.maxlen, ss = this.suite; this.suites.forEach(function(s) { ss.add(s[0] + new Array(maxlen-s[0].length+1).join(" "), s[1]); }); if(this.suites.length > 0) this.suite.run(); diff --git a/perf/bstr.js b/perf/bstr.js index 097a66e..a27d0fd 100644 --- a/perf/bstr.js +++ b/perf/bstr.js @@ -7,77 +7,97 @@ function strToArr(str) { }); } - function crcTable(arr, append) { - var crc, i, l; +function crcTable(arr, append) { + var crc, i, l; - // if we're in append mode, don't reset crc - // if arr is null or undefined, reset table and return - if (typeof crcTable.crc === 'undefined' || !append || !arr) { - crcTable.crc = 0 ^ -1; + // if we're in append mode, don't reset crc + // if arr is null or undefined, reset table and return + if (typeof crcTable.crc === 'undefined' || !append || !arr) { + crcTable.crc = 0 ^ -1; - if (!arr) { - return; - } + if (!arr) { + return; } - - // store in temp variable for minor speed gain - crc = crcTable.crc; - - for (i = 0, l = arr.length; i < l; i += 1) { - crc = (crc >>> 8) ^ table[(crc ^ arr[i]) & 0xff]; - } - - crcTable.crc = crc; - - return crc ^ -1; } + // store in temp variable for minor speed gain + crc = crcTable.crc; + + for (i = 0, l = arr.length; i < l; i += 1) { + crc = (crc >>> 8) ^ table[(crc ^ arr[i]) & 0xff]; + } + + crcTable.crc = crc; + + return crc ^ -1; +} + function node_crc32(bstr) { return crcTable(strToArr(bstr)); } -function sheetjs1(bstr) { - for(var crc = -1, i = 0; i != bstr.length; ++i) { +function sheetjs1(bstr) { + for(var crc = -1, i = 0; i < bstr.length; ++i) { crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i)) & 0xFF]; } return crc ^ -1; } -function sheetjs2(bstr) { - for(var crc = -1, i = 0, L=bstr.length-1; i < L;) { +function sheetjs2(bstr) { + var L = bstr.length - 1; + for(var crc = -1, i = 0; i < L;) { crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF]; crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF]; } - if(i === L) crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF]; + if(i === bstr.length - 1) crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i)) & 0xFF]; return crc ^ -1; } -function sheetjs3(bstr) { +function sheetjs3(bstr) { for(var crc = -1, i = 0, L=bstr.length-2; i < L;) { crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF]; crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF]; crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF]; } - if(i === L++) crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF]; - if(i === L++) crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF]; + while(i < L+2) crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF]; return crc ^ -1; } +function sheetjs8(bstr) { + for(var crc = -1, i = 0, L=bstr.length-7; i < L;) { + crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF]; + crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF]; + crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF]; + crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF]; + crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF]; + crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF]; + crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF]; + crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF]; + } + while(i < L+7) crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i++)) & 0xFF]; + return crc ^ -1; +} + +var w = 2000; +var base = new Array(w); +for(var i = 0; i !== w; ++i) base[i] = String.fromCharCode((Math.random()*256)&255); +var b = new Array(w); +for(var i = 0; i !== w; ++i) b[i] = ""+base.slice(0,i).join(""); + +var assert = require('assert'); +for(var i = 0; i !== w; ++i) { + var foobar = b[i]; + assert.equal(node_crc32(foobar), sheetjs1(foobar)); + assert.equal(node_crc32(foobar), sheetjs2(foobar)); + assert.equal(node_crc32(foobar), sheetjs3(foobar)); + assert.equal(node_crc32(foobar), sheetjs8(foobar)); +} + var BM = require('./bm'); var suite = new BM('binary string'); - -var foobar = "foobarbazqux"; -foobar += " " + foobar; -foobar += " " + foobar; -foobar += " " + foobar; -foobar += " " + foobar; -suite.add('npm crc32', function() { for(var j = 0; j != 1000; ++j) node_crc32(foobar); }); -suite.add('sheetjs 1', function() { for(var j = 0; j != 1000; ++j) sheetjs1(foobar); }); -suite.add('sheetjs 2', function() { for(var j = 0; j != 1000; ++j) sheetjs2(foobar); }); -suite.add('sheetjs 3', function() { for(var j = 0; j != 1000; ++j) sheetjs3(foobar); }); +suite.add('npm crc32', function() { for(var j = 0; j !== w; ++j) node_crc32(b[j]); }); +suite.add('sheetjs 1', function() { for(var j = 0; j !== w; ++j) sheetjs1(b[j]); }); +suite.add('sheetjs 2', function() { for(var j = 0; j !== w; ++j) sheetjs2(b[j]); }); +suite.add('sheetjs 3', function() { for(var j = 0; j !== w; ++j) sheetjs3(b[j]); }); +suite.add('sheetjs 8', function() { for(var j = 0; j !== w; ++j) sheetjs8(b[j]); }); suite.run(); - -var assert = require('assert'); -assert.equal(node_crc32(foobar), sheetjs1(foobar)); -assert.equal(node_crc32(foobar), sheetjs2(foobar)); -assert.equal(node_crc32(foobar), sheetjs3(foobar)); diff --git a/perf/utf8.js b/perf/utf8.js index ba0c1a4..2437cb8 100644 --- a/perf/utf8.js +++ b/perf/utf8.js @@ -35,10 +35,7 @@ var BM = require('./bm'); var suite = new BM('unicode string'); var foobar = "foo bar baz٪☃🍣"; -foobar += " " + foobar; -foobar += " " + foobar; -foobar += " " + foobar; -foobar += " " + foobar; +for(var i = 0; i != 4; ++i) foobar += " " + foobar; suite.add('sheetjs 1', function() { for(var j = 0; j != 1000; ++j) sheetjs1(foobar); }); suite.add('sheetjs 2', function() { for(var j = 0; j != 1000; ++j) sheetjs2(foobar); }); suite.run()