From 5a7e4db9732178f9829afe6edabc128324e062e0 Mon Sep 17 00:00:00 2001 From: SheetJS Date: Wed, 12 Oct 2016 15:44:45 -0400 Subject: [PATCH] version bump 1.0.1: bstr performance The buffer fallback is incredibly slow --- .gitignore | 1 + Makefile | 2 +- bits/01_version.js | 2 +- bits/40_crc.js | 5 +- crc32.flow.js | 7 +-- crc32.js | 5 +- ctest/crc32.js | 5 +- ctest/fixtures.js | 137 ++++---------------------------------------- ctest/test.js | 4 +- misc/bits.js | 12 +++- misc/integration.js | 125 ---------------------------------------- misc/perf.sh | 18 ------ package.json | 2 +- perf/bstr.js | 50 ++++++++++------ perf/utf8.js | 34 ++++++++--- test.js | 4 +- 16 files changed, 95 insertions(+), 318 deletions(-) delete mode 100644 misc/integration.js delete mode 100755 misc/perf.sh diff --git a/.gitignore b/.gitignore index 1d607da..0365d5f 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ test_files/*.py test_files/*.js test_files/baseline* misc/coverage.html +ctest/sauce* diff --git a/Makefile b/Makefile index 302fd6b..569a2af 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ clean: clean-baseline ## Remove targets and build artifacts .PHONY: test mocha test mocha: test.js $(TARGET) baseline ## Run test suite - mocha -R spec -t 20000 + mocha -R spec -t 30000 .PHONY: ctest ctest: ## Build browser test (into ctest/ subdirectory) diff --git a/bits/01_version.js b/bits/01_version.js index d9dd0f3..1d455a5 100644 --- a/bits/01_version.js +++ b/bits/01_version.js @@ -1 +1 @@ -CRC32.version = '1.0.0'; +CRC32.version = '1.0.1'; diff --git a/bits/40_crc.js b/bits/40_crc.js index bd2cbb6..b6fa7f9 100644 --- a/bits/40_crc.js +++ b/bits/40_crc.js @@ -1,8 +1,5 @@ /*# charCodeAt is the best approach for binary strings */ -/*global Buffer */ -var use_buffer = typeof Buffer !== 'undefined'; function crc32_bstr(bstr/*:string*/, seed/*:?CRC32Type*/)/*:CRC32Type*/ { - if(bstr.length > 32768) if(use_buffer) return crc32_buf_8(new Buffer(bstr), seed); var C = seed/*:: ? 0 : 0 */ ^ -1, L = bstr.length - 1; for(var i = 0; i < L;) { C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF]; @@ -41,7 +38,7 @@ function crc32_buf_8(buf/*:ABuf*/, seed/*:?CRC32Type*/)/*:CRC32Type*/ { return C ^ -1; } -/*# much much faster to intertwine utf8 and C */ +/*# much much faster to intertwine utf8 and crc */ function crc32_str(str/*:string*/, seed/*:?CRC32Type*/)/*:CRC32Type*/ { var C = seed/*:: ? 0 : 0 */ ^ -1; for(var i = 0, L=str.length, c, d; i < L;) { diff --git a/crc32.flow.js b/crc32.flow.js index 422724c..0e61492 100644 --- a/crc32.flow.js +++ b/crc32.flow.js @@ -23,7 +23,7 @@ var CRC32; } /*jshint ignore:end */ }(function(CRC32) { -CRC32.version = '1.0.0'; +CRC32.version = '1.0.1'; /*:: type CRC32Type = number; type ABuf = Array | Buffer; @@ -52,10 +52,7 @@ function signed_crc_table()/*:CRC32TableType*/ { var T = signed_crc_table(); /*# charCodeAt is the best approach for binary strings */ -/*global Buffer */ -var use_buffer = typeof Buffer !== 'undefined'; function crc32_bstr(bstr/*:string*/, seed/*:?CRC32Type*/)/*:CRC32Type*/ { - if(bstr.length > 32768) if(use_buffer) return crc32_buf_8(new Buffer(bstr), seed); var C = seed/*:: ? 0 : 0 */ ^ -1, L = bstr.length - 1; for(var i = 0; i < L;) { C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF]; @@ -94,7 +91,7 @@ function crc32_buf_8(buf/*:ABuf*/, seed/*:?CRC32Type*/)/*:CRC32Type*/ { return C ^ -1; } -/*# much much faster to intertwine utf8 and C */ +/*# much much faster to intertwine utf8 and crc */ function crc32_str(str/*:string*/, seed/*:?CRC32Type*/)/*:CRC32Type*/ { var C = seed/*:: ? 0 : 0 */ ^ -1; for(var i = 0, L=str.length, c, d; i < L;) { diff --git a/crc32.js b/crc32.js index 5bf1634..d7a0bb3 100644 --- a/crc32.js +++ b/crc32.js @@ -21,7 +21,7 @@ var CRC32; } /*jshint ignore:end */ }(function(CRC32) { -CRC32.version = '1.0.0'; +CRC32.version = '1.0.1'; /* see perf/crc32table.js */ /*global Int32Array */ function signed_crc_table() { @@ -44,10 +44,7 @@ function signed_crc_table() { } var T = signed_crc_table(); -/*global Buffer */ -var use_buffer = typeof Buffer !== 'undefined'; function crc32_bstr(bstr, seed) { - if(bstr.length > 32768) if(use_buffer) return crc32_buf_8(new Buffer(bstr), seed); var C = seed ^ -1, L = bstr.length - 1; for(var i = 0; i < L;) { C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF]; diff --git a/ctest/crc32.js b/ctest/crc32.js index 5bf1634..d7a0bb3 100644 --- a/ctest/crc32.js +++ b/ctest/crc32.js @@ -21,7 +21,7 @@ var CRC32; } /*jshint ignore:end */ }(function(CRC32) { -CRC32.version = '1.0.0'; +CRC32.version = '1.0.1'; /* see perf/crc32table.js */ /*global Int32Array */ function signed_crc_table() { @@ -44,10 +44,7 @@ function signed_crc_table() { } var T = signed_crc_table(); -/*global Buffer */ -var use_buffer = typeof Buffer !== 'undefined'; function crc32_bstr(bstr, seed) { - if(bstr.length > 32768) if(use_buffer) return crc32_buf_8(new Buffer(bstr), seed); var C = seed ^ -1, L = bstr.length - 1; for(var i = 0; i < L;) { C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF]; diff --git a/ctest/fixtures.js b/ctest/fixtures.js index 78c2533..b84d6c8 100644 --- a/ctest/fixtures.js +++ b/ctest/fixtures.js @@ -1,12 +1,22 @@ var o = "foo bar baz٪☃🍣"; var m = "foobar"; for(var i = 0; i != 11; ++i) m+=m; +var m1 = m + m, m2 = m1 + m1, m3 = m2 + m2, m4 = m3 + m3; +var M1 = m + "𝑹" + m, M2 = M1 + "𝐀" + M1, M3 = M2 + "𝓜" + M2, M4 = M3 + "𝙖" + M3; var bits = [ [ "foobar", -1628037227, 1 ], [ "foo bar baz", -228401567, 1 ], [ "foo bar baz٪", 984445192 ], [ "foo bar baz٪☃", 140429620], [ m, 40270464, 1 ], - [ o, 1531648243], + [ m1, -239917269, 1], + [ m2, 2048324365, 1 ], + [ m3, -1695517393, 1 ], + [ m4, 1625284864, 1 ], + [ M1, 642113519 ], + [ M2, -1441250016 ], + [ M3, -1101021992 ], + [ M4, -1610723860 ], + [ o, 1531648243 ], [ o+o, -218791105 ], [ o+o+o, 1834240887 ] ]; @@ -35,131 +45,6 @@ declare module 'printj' { declare function sprintf(fmt:string, ...args:any):string; }; */ -/* 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'); - -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)|0;} -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)|0; } -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, 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; - case "C": ntests = 10000; len_max = 4096; break; - case "D": ntests = 1000; len_max = 16384; break; - case "E": ntests = 1000; len_max = 65536; break; - case "F": ntests = 100; len_max = 262144; break; - case "G": ntests = 100; len_max = 1048576; break; - case "H": ntests = 10; len_max = 4194304; break; - case "I": ntests = 10; len_max = 16777216; break; - default: ntests = 10000; len_max = 1024; break; -} - -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 = []; -var len_min = 1; - -var corpus = new Array(0x0800); -for(var k = 0; k < 0x0800; ++k) corpus[k] = String.fromCharCode(k) -len_max --; - -k = (Math.random()*0x800)|0; -for(var i = 0; i < ntests; ++i) { - var l = (Math.random() * (len_max - len_min))|0 + len_min; - var s = new Array(l), t = new Array(l); - if(btest) for(var j = 0; j < l; ++j) s[j] = corpus[(i+j+k)&127]; - if(utest) for(var j = 0; j < l; ++j) t[j] = corpus[(i+j+k)&0x7FF]; - var ss = s.join(""); - bstr_tests[i] = [ss, new Buffer(ss)]; - ustr_tests[i] = t.join(""); -} - -var assert = require('assert'); -function fix(str) { return parseInt(str, 16)|0; } -if(btest) for(var j = 0; j != ntests; ++j) { - if(do_bstr && do_buf) assert.equal(z1(bstr_tests[j][0]), b1(bstr_tests[j][1])); - - 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]), (z4(bstr_tests[j][0]))); - assert.equal(z1(bstr_tests[j][0]), z5(bstr_tests[j][0])); - } - - 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]), (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/ctest/test.js b/ctest/test.js index f6ccf13..4b0f0a4 100644 --- a/ctest/test.js +++ b/ctest/test.js @@ -36,11 +36,13 @@ describe('crc32 bits', function() { var msg = i[0], l = i[0].length, L = i[1]|0; if(l > 20) msg = i[0].substr(0,5) + "...(" + l + ")..." + i[0].substr(-5); if(l > 100 && msieversion() < 9) return; + if(l > 20000 && typeof Buffer === 'undefined') return; it(msg, function() { if(i[2] === 1) assert.equal(X.bstr(i[0]), L); assert.equal(X.str(i[0]), i[1]|0); if(typeof Buffer !== 'undefined') assert.equal(X.buf(new Buffer(i[0])), L); - for(var x = 0; x < i[0].length; ++x) { + var len = i[0].length, step = len < 20000 ? 1 : len < 50000 ? Math.ceil(len / 20000) : Math.ceil(len / 2000); + for(var x = 0; x < len; x += step) { if(i[0].charCodeAt(x) >= 0xD800 && i[0].charCodeAt(x) < 0xE000) continue; if(i[2] === 1) { var bstrcrc = X.bstr(i[0].substr(x), X.bstr(i[0].substr(0, x))); diff --git a/misc/bits.js b/misc/bits.js index a4d2542..7cc8544 100644 --- a/misc/bits.js +++ b/misc/bits.js @@ -1,12 +1,22 @@ var o = "foo bar baz٪☃🍣"; var m = "foobar"; for(var i = 0; i != 11; ++i) m+=m; +var m1 = m + m, m2 = m1 + m1, m3 = m2 + m2, m4 = m3 + m3; +var M1 = m + "𝑹" + m, M2 = M1 + "𝐀" + M1, M3 = M2 + "𝓜" + M2, M4 = M3 + "𝙖" + M3; var bits = [ [ "foobar", -1628037227, 1 ], [ "foo bar baz", -228401567, 1 ], [ "foo bar baz٪", 984445192 ], [ "foo bar baz٪☃", 140429620], [ m, 40270464, 1 ], - [ o, 1531648243], + [ m1, -239917269, 1], + [ m2, 2048324365, 1 ], + [ m3, -1695517393, 1 ], + [ m4, 1625284864, 1 ], + [ M1, 642113519 ], + [ M2, -1441250016 ], + [ M3, -1101021992 ], + [ M4, -1610723860 ], + [ o, 1531648243 ], [ o+o, -218791105 ], [ o+o+o, 1834240887 ] ]; diff --git a/misc/integration.js b/misc/integration.js deleted file mode 100644 index f6019c4..0000000 --- a/misc/integration.js +++ /dev/null @@ -1,125 +0,0 @@ -/* 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'); - -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)|0;} -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)|0; } -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, 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; - case "C": ntests = 10000; len_max = 4096; break; - case "D": ntests = 1000; len_max = 16384; break; - case "E": ntests = 1000; len_max = 65536; break; - case "F": ntests = 100; len_max = 262144; break; - case "G": ntests = 100; len_max = 1048576; break; - case "H": ntests = 10; len_max = 4194304; break; - case "I": ntests = 10; len_max = 16777216; break; - default: ntests = 10000; len_max = 1024; break; -} - -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 = []; -var len_min = 1; - -var corpus = new Array(0x0800); -for(var k = 0; k < 0x0800; ++k) corpus[k] = String.fromCharCode(k) -len_max --; - -k = (Math.random()*0x800)|0; -for(var i = 0; i < ntests; ++i) { - var l = (Math.random() * (len_max - len_min))|0 + len_min; - var s = new Array(l), t = new Array(l); - if(btest) for(var j = 0; j < l; ++j) s[j] = corpus[(i+j+k)&127]; - if(utest) for(var j = 0; j < l; ++j) t[j] = corpus[(i+j+k)&0x7FF]; - var ss = s.join(""); - bstr_tests[i] = [ss, new Buffer(ss)]; - ustr_tests[i] = t.join(""); -} - -var assert = require('assert'); -function fix(str) { return parseInt(str, 16)|0; } -if(btest) for(var j = 0; j != ntests; ++j) { - if(do_bstr && do_buf) assert.equal(z1(bstr_tests[j][0]), b1(bstr_tests[j][1])); - - 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]), (z4(bstr_tests[j][0]))); - assert.equal(z1(bstr_tests[j][0]), z5(bstr_tests[j][0])); - } - - 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]), (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 deleted file mode 100755 index a4f36d4..0000000 --- a/misc/perf.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -cd misc &>/dev/null - -git_module() { - if [ ! -e "$1/" ]; then git clone $2; fi - cd "$1" - git pull - cd - &>/dev/null -} - -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 G H I; do MODE="$i" node integration.js "$1"; done diff --git a/package.json b/package.json index c33d3f2..745d2b8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "crc-32", - "version": "1.0.0", + "version": "1.0.1", "author": "sheetjs", "description": "Pure-JS CRC-32", "keywords": [ "crc32", "checksum", "crc" ], diff --git a/perf/bstr.js b/perf/bstr.js index ee411e3..1db9f01 100644 --- a/perf/bstr.js +++ b/perf/bstr.js @@ -38,6 +38,14 @@ function node_crc32(bstr) { return crcTable(strToArr(bstr)); } +function sheetjsB(bstr) { + var b = new Buffer(bstr, 'binary'); + for(var crc = -1, i = 0; i < b.length; ++i) { + crc = (crc >>> 8) ^ table[(crc ^ b[i]) & 0xFF]; + } + return crc ^ -1; +} + function sheetjs1(bstr) { for(var crc = -1, i = 0; i < bstr.length; ++i) { crc = (crc >>> 8) ^ table[(crc ^ bstr.charCodeAt(i)) & 0xFF]; @@ -80,30 +88,34 @@ function sheetjs8(bstr) { 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 w = 80000; var b = new Array(w); -for(var i = 0; i !== w; ++i) b[i] = ""+base.slice(0,i).join(""); +b[0] = ""; +for(var i = 1; i !== w; ++i) b[i] = b[i-1] + String.fromCharCode((Math.random()*256)&255); + 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)); - assert.equal(node_crc32(foobar), old(foobar)); - assert.equal(node_crc32(foobar), cur(foobar)); +function check(foobar) { + var baseline = old(foobar); + assert.equal(baseline, sheetjs1(foobar)); + assert.equal(baseline, sheetjs2(foobar)); + assert.equal(baseline, sheetjs3(foobar)); + assert.equal(baseline, sheetjs8(foobar)); + assert.equal(baseline, sheetjsB(foobar)); + assert.equal(baseline, cur(foobar)); + if(i < 100) assert.equal(baseline, node_crc32(foobar)); } +for(var i = 0; i !== w; ++i) { + var foobar = b[i]; +} var BM = require('./bm'); var suite = new BM('binary string'); -//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.add('last vers', function() { for(var j = 0; j !== w; ++j) old(b[j]); }); -suite.add('current v', function() { for(var j = 0; j !== w; ++j) cur(b[j]); }); +suite.add('sheetjs 1', function() { for(var j = 0; j !== w; j+=100) sheetjs1(b[j]); }); +suite.add('sheetjs 2', function() { for(var j = 0; j !== w; j+=100) sheetjs2(b[j]); }); +suite.add('sheetjs 3', function() { for(var j = 0; j !== w; j+=100) sheetjs3(b[j]); }); +suite.add('sheetjs 8', function() { for(var j = 0; j !== w; j+=100) sheetjs8(b[j]); }); +suite.add('sheetjs B', function() { for(var j = 0; j !== w; j+=100) sheetjsB(b[j]); }); +suite.add('last vers', function() { for(var j = 0; j !== w; j+=100) old(b[j]); }); +suite.add('current v', function() { for(var j = 0; j !== w; j+=100) cur(b[j]); }); suite.run(); diff --git a/perf/utf8.js b/perf/utf8.js index 94c5643..9365663 100644 --- a/perf/utf8.js +++ b/perf/utf8.js @@ -38,16 +38,36 @@ var foobar = "foo bar baz٪☃🍣"; for(var i = 0; i != 4; ++i) foobar += " " + foobar; var assert = require('assert'); -{ - assert.equal(sheetjs1(foobar), sheetjs2(foobar)); - assert.equal(sheetjs1(foobar), old(foobar)); - assert.equal(sheetjs1(foobar), cur(foobar)); +function check(foobar) { + var baseline = old(foobar); + assert.equal(baseline, sheetjs1(foobar)); + assert.equal(baseline, sheetjs2(foobar)); + assert.equal(baseline, cur(foobar)); } var BM = require('./bm'); -var suite = new BM('unicode string'); +var suite = new BM('unicode string (' + foobar.length + ')'); 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('last vers', function() { for(var j = 0; j != 1000; ++j) old(foobar); }); -suite.add('current v', function() { for(var j = 0; j != 1000; ++j) cur(foobar); }); +suite.add('last vers', function() { for(var j = 0; j != 1000; ++j) old(foobar, 0) ; }); +suite.add('current v', function() { for(var j = 0; j != 1000; ++j) cur(foobar, 0); }); suite.run(); + +function doit(foobar) { + check(foobar); + var s = new BM('unicode string (' + foobar.length + ')'); + s.add('sheetjs 1', function() { sheetjs1(foobar); }); + s.add('sheetjs 2', function() { sheetjs2(foobar); }); + s.add('last vers', function() { old(foobar, 0); }); + s.add('current v', function() { cur(foobar, 0); }); + s.run(); +} + +for(var i = 0; i != 4; ++i) foobar += " " + foobar; +doit(foobar); + +foobar += " " + foobar; +doit(foobar); + +foobar += " " + foobar; +doit(foobar); diff --git a/test.js b/test.js index f6ccf13..4b0f0a4 100644 --- a/test.js +++ b/test.js @@ -36,11 +36,13 @@ describe('crc32 bits', function() { var msg = i[0], l = i[0].length, L = i[1]|0; if(l > 20) msg = i[0].substr(0,5) + "...(" + l + ")..." + i[0].substr(-5); if(l > 100 && msieversion() < 9) return; + if(l > 20000 && typeof Buffer === 'undefined') return; it(msg, function() { if(i[2] === 1) assert.equal(X.bstr(i[0]), L); assert.equal(X.str(i[0]), i[1]|0); if(typeof Buffer !== 'undefined') assert.equal(X.buf(new Buffer(i[0])), L); - for(var x = 0; x < i[0].length; ++x) { + var len = i[0].length, step = len < 20000 ? 1 : len < 50000 ? Math.ceil(len / 20000) : Math.ceil(len / 2000); + for(var x = 0; x < len; x += step) { if(i[0].charCodeAt(x) >= 0xD800 && i[0].charCodeAt(x) < 0xE000) continue; if(i[2] === 1) { var bstrcrc = X.bstr(i[0].substr(x), X.bstr(i[0].substr(0, x)));