version bump 0.2.0: safari performance
On Safari, bit twiddling is 50% faster than directly evaluating mod 65521
This commit is contained in:
parent
b53334db84
commit
d0e9ff9b3d
11
README.md
11
README.md
@ -51,6 +51,17 @@ decisions in the code).
|
||||
|
||||
[js-crc](http://git.io/crc32) has more performance notes
|
||||
|
||||
Bit twiddling is much faster than taking the mod on Safari and older Firefoxes.
|
||||
Instead of taking the literal mod 65521, it is faster to keep it in the integers
|
||||
by bit-shifting: `65536 ~ 15 mod 65521` so for nonnegative integer `a`:
|
||||
|
||||
```
|
||||
a = (a >>> 16) * 65536 + (a & 65535) [equality]
|
||||
a ~ (a >>> 16) * 15 + (a & 65535) mod 65521
|
||||
```
|
||||
|
||||
The mod is taken at the very end, since the intermediate result may exceed 65521
|
||||
|
||||
## Magic Number
|
||||
|
||||
The magic numbers were chosen so as to not overflow a 31-bit integer:
|
||||
|
26
adler32.js
26
adler32.js
@ -10,29 +10,29 @@ function adler32_bstr(bstr) {
|
||||
if(bstr.length > 32768) if(use_buffer) return adler32_buf(Buffer(bstr));
|
||||
var a = 1, b = 0, L = bstr.length, M;
|
||||
for(var i = 0; i < L;) {
|
||||
M = Math.min(L-i, 3854);
|
||||
for(;M>0;--M) {
|
||||
a += bstr.charCodeAt(i++);
|
||||
M = Math.min(L-i, 3850)+i;
|
||||
for(;i<M;i++) {
|
||||
a += bstr.charCodeAt(i);
|
||||
b += a;
|
||||
}
|
||||
a %= 65521;
|
||||
b %= 65521;
|
||||
a = (15*(a>>>16)+(a&65535))
|
||||
b = (15*(b>>>16)+(b&65535))
|
||||
}
|
||||
return b > 32767 ? (((b - 65536) * 65536) | a) : ((b * 65536) | a);
|
||||
return ((b%65521) << 16) | (a%65521);
|
||||
}
|
||||
|
||||
function adler32_buf(buf) {
|
||||
var a = 1, b = 0, L = buf.length, M;
|
||||
for(var i = 0; i < L;) {
|
||||
M = Math.min(L-i, 3854);
|
||||
for(;M>0;--M) {
|
||||
a += buf[i++];
|
||||
M = Math.min(L-i, 3850)+i;
|
||||
for(;i<M;i++) {
|
||||
a += buf[i];
|
||||
b += a;
|
||||
}
|
||||
a %= 65521;
|
||||
b %= 65521;
|
||||
a = (15*(a>>>16)+(a&65535))
|
||||
b = (15*(b>>>16)+(b&65535))
|
||||
}
|
||||
return b > 32767 ? (((b - 65536) * 65536) | a) : ((b * 65536) | a);
|
||||
return ((b%65521) << 16) | (a%65521);
|
||||
}
|
||||
|
||||
/* much much faster to intertwine utf8 and adler */
|
||||
@ -61,7 +61,7 @@ function adler32_str(str) {
|
||||
a %= 65521;
|
||||
b %= 65521;
|
||||
}
|
||||
return b > 32767 ? (((b - 65536) * 65536) | a) : ((b * 65536) | a);
|
||||
return (b << 16) | a;
|
||||
}
|
||||
ADLER32.bstr = adler32_bstr;
|
||||
ADLER32.buf = adler32_buf;
|
||||
|
@ -5,29 +5,29 @@ function adler32_bstr(bstr) {
|
||||
if(bstr.length > 32768) if(use_buffer) return adler32_buf(Buffer(bstr));
|
||||
var a = 1, b = 0, L = bstr.length, M;
|
||||
for(var i = 0; i < L;) {
|
||||
M = Math.min(L-i, 3854);
|
||||
for(;M>0;--M) {
|
||||
a += bstr.charCodeAt(i++);
|
||||
M = Math.min(L-i, 3850)+i;
|
||||
for(;i<M;i++) {
|
||||
a += bstr.charCodeAt(i);
|
||||
b += a;
|
||||
}
|
||||
a %= 65521;
|
||||
b %= 65521;
|
||||
a = (15*(a>>>16)+(a&65535))
|
||||
b = (15*(b>>>16)+(b&65535))
|
||||
}
|
||||
return b > 32767 ? (((b - 65536) * 65536) | a) : ((b * 65536) | a);
|
||||
return ((b%65521) << 16) | (a%65521);
|
||||
}
|
||||
|
||||
function adler32_buf(buf) {
|
||||
var a = 1, b = 0, L = buf.length, M;
|
||||
for(var i = 0; i < L;) {
|
||||
M = Math.min(L-i, 3854);
|
||||
for(;M>0;--M) {
|
||||
a += buf[i++];
|
||||
M = Math.min(L-i, 3850)+i;
|
||||
for(;i<M;i++) {
|
||||
a += buf[i];
|
||||
b += a;
|
||||
}
|
||||
a %= 65521;
|
||||
b %= 65521;
|
||||
a = (15*(a>>>16)+(a&65535))
|
||||
b = (15*(b>>>16)+(b&65535))
|
||||
}
|
||||
return b > 32767 ? (((b - 65536) * 65536) | a) : ((b * 65536) | a);
|
||||
return ((b%65521) << 16) | (a%65521);
|
||||
}
|
||||
|
||||
/* much much faster to intertwine utf8 and adler */
|
||||
@ -56,5 +56,5 @@ function adler32_str(str) {
|
||||
a %= 65521;
|
||||
b %= 65521;
|
||||
}
|
||||
return b > 32767 ? (((b - 65536) * 65536) | a) : ((b * 65536) | a);
|
||||
return (b << 16) | a;
|
||||
}
|
||||
|
@ -10,29 +10,29 @@ function adler32_bstr(bstr) {
|
||||
if(bstr.length > 32768) if(use_buffer) return adler32_buf(Buffer(bstr));
|
||||
var a = 1, b = 0, L = bstr.length, M;
|
||||
for(var i = 0; i < L;) {
|
||||
M = Math.min(L-i, 3854);
|
||||
for(;M>0;--M) {
|
||||
a += bstr.charCodeAt(i++);
|
||||
M = Math.min(L-i, 3850)+i;
|
||||
for(;i<M;i++) {
|
||||
a += bstr.charCodeAt(i);
|
||||
b += a;
|
||||
}
|
||||
a %= 65521;
|
||||
b %= 65521;
|
||||
a = (15*(a>>>16)+(a&65535))
|
||||
b = (15*(b>>>16)+(b&65535))
|
||||
}
|
||||
return b > 32767 ? (((b - 65536) * 65536) | a) : ((b * 65536) | a);
|
||||
return ((b%65521) << 16) | (a%65521);
|
||||
}
|
||||
|
||||
function adler32_buf(buf) {
|
||||
var a = 1, b = 0, L = buf.length, M;
|
||||
for(var i = 0; i < L;) {
|
||||
M = Math.min(L-i, 3854);
|
||||
for(;M>0;--M) {
|
||||
a += buf[i++];
|
||||
M = Math.min(L-i, 3850)+i;
|
||||
for(;i<M;i++) {
|
||||
a += buf[i];
|
||||
b += a;
|
||||
}
|
||||
a %= 65521;
|
||||
b %= 65521;
|
||||
a = (15*(a>>>16)+(a&65535))
|
||||
b = (15*(b>>>16)+(b&65535))
|
||||
}
|
||||
return b > 32767 ? (((b - 65536) * 65536) | a) : ((b * 65536) | a);
|
||||
return ((b%65521) << 16) | (a%65521);
|
||||
}
|
||||
|
||||
/* much much faster to intertwine utf8 and adler */
|
||||
@ -61,7 +61,7 @@ function adler32_str(str) {
|
||||
a %= 65521;
|
||||
b %= 65521;
|
||||
}
|
||||
return b > 32767 ? (((b - 65536) * 65536) | a) : ((b * 65536) | a);
|
||||
return (b << 16) | a;
|
||||
}
|
||||
ADLER32.bstr = adler32_bstr;
|
||||
ADLER32.buf = adler32_buf;
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "adler-32",
|
||||
"version": "0.1.0",
|
||||
"version": "0.2.0",
|
||||
"author": "sheetjs",
|
||||
"description": "Pure-JS ADLER-32",
|
||||
"keywords": [ "adler32", "checksum" ],
|
||||
|
48
perf/bstr.js
48
perf/bstr.js
@ -1,5 +1,3 @@
|
||||
var table = require('../').table;
|
||||
|
||||
function sheetjs1(bstr) {
|
||||
var a = 1, b = 0, L = bstr.length;
|
||||
for(var i = 0; i < L;) {
|
||||
@ -14,7 +12,21 @@ function sheetjs1(bstr) {
|
||||
function sheetjs2(bstr) {
|
||||
var a = 1, b = 0, L = bstr.length, M;
|
||||
for(var i = 0; i < L;) {
|
||||
M = Math.min(L-i, 3854);
|
||||
M = Math.min(L-i, 3850)+i;
|
||||
for(;i<M;i++) {
|
||||
a += bstr.charCodeAt(i);
|
||||
b += a;
|
||||
}
|
||||
a = (15*(a>>>16)+(a&65535))
|
||||
b = (15*(b>>>16)+(b&65535))
|
||||
}
|
||||
return ((b%65521) << 16) | (a%65521);
|
||||
}
|
||||
|
||||
function sheetjs3(bstr) {
|
||||
var a = 1, b = 0, L = bstr.length, M;
|
||||
for(var i = 0; i < L;) {
|
||||
M = Math.min(L-i, 5552);
|
||||
for(;M>0;--M) {
|
||||
a += bstr.charCodeAt(i++);
|
||||
b += a;
|
||||
@ -25,14 +37,28 @@ function sheetjs2(bstr) {
|
||||
return (b << 16) | a;
|
||||
}
|
||||
|
||||
var foobar = "foobarbazqux";
|
||||
for(var i = 0; i != 11; ++i) foobar += " " + foobar;
|
||||
var foobar = [255,255,255,255,255,255].map(function(x) { return String.fromCharCode(x); }).join("");
|
||||
foobar += foobar;
|
||||
foobar += foobar;
|
||||
foobar += foobar;
|
||||
foobar += foobar;
|
||||
foobar += foobar;
|
||||
foobar += foobar;
|
||||
foobar.charCodeAt(0);
|
||||
var m = 2048;
|
||||
var assert = require('assert');
|
||||
assert.equal(sheetjs1(foobar), sheetjs2(foobar));
|
||||
|
||||
var BM = require('./bm');
|
||||
var suite = new BM('binary string');
|
||||
for(var i = 0; i != 14; ++i) {
|
||||
foobar += foobar;
|
||||
foobar.charCodeAt(0);
|
||||
assert.equal(sheetjs1(foobar), sheetjs3(foobar));
|
||||
assert.equal(sheetjs1(foobar), sheetjs2(foobar));
|
||||
//for(var j = 0; j != 200; ++j) assert.equal(sheetjs2(foobar), sheetjs3(foobar));
|
||||
var suite = new BM('binary 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.run();
|
||||
if(i<3) suite.add('sheetjs 1', function() { for(var j = 0; j != m; ++j) sheetjs1(foobar); });
|
||||
suite.add('sheetjs 2', function() { for(var j = 0; j != m; ++j) sheetjs2(foobar); });
|
||||
suite.add('sheetjs 3', function() { for(var j = 0; j != m; ++j) sheetjs3(foobar); });
|
||||
suite.run();
|
||||
m>>>=1; if(m < 10) m = 10;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user