Issues with compression in javascript
我有一个要压缩的对象。它的形式
1 2 3 4 5 6 7 8 9 10 11 | [ { array string }, { array string }, ... ] |
数组的长度不超过10-15,与字符串相比非常小(它们是html,长度约为170k)。字符串通常是重复的,或者有大量的重叠。所以我的直觉告诉我,压缩值应该是1个字符串的压缩值,外加一点额外的值。
我用JSON.stringify这个对象并尝试压缩。
大多数压缩库在压缩字符串方面做得不好,因为服务器向我发送了77kb的gzip压缩版本,所以我知道它至少可以这么小。
gzip-js
lzma-js
在我尝试的15个库中做得很好。
问题是gzip-js的字符串数是线性的。但是lzma可以正确地做到这一点,它的大小只会稍微增加一点。
不幸的是,当压缩7mbs(大约30个字符串)时,lzma-js(级别2)非常慢(20s vs 1s gzip)。
是否有一个compressopn库,大约与gzip一样快,但是不能在重复字符串上线性扩展?
Pako对我有用,请尝试一下:
就像在这里完成操作一样,不使用byte ID而是使用byteArrays。
获取pako.js,您可以像这样解压缩byteArray:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <html> <head> Gunzipping binary gzipped string <script type="text/javascript" src="pako.js"> <script type="text/javascript"> // Get datastream as Array, for example: var charData = [31,139,8,0,0,0,0,0,0,3,5,193,219,13,0,16,16,4,192,86,214,151,102,52,33,110,35,66,108,226,60,218,55,147,164,238,24,173,19,143,241,18,85,27,58,203,57,46,29,25,198,34,163,193,247,106,179,134,15,50,167,173,148,48,0,0,0]; // Turn number array into byte-array var binData = new Uint8Array(charData); // Pako magic var data = pako.inflate(binData); // Convert gunzipped byteArray back to ascii string: var strData = String.fromCharCode.apply(null, new Uint16Array(data)); // Output to console console.log(strData); </head> <body> Open up the developer console. </body> </html> |
正在运行的示例:http://jsfiddle.net/9yH7M/
另外,在发送数组之前,您可以对数组进行base64编码,因为当以JSON或XML格式发送时,数组会占用很多开销。 同样解码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // Get some base64 encoded binary data from the server. Imagine we got this: var b64Data = 'H4sIAAAAAAAAAwXB2w0AEBAEwFbWl2Y0IW4jQmziPNo3k6TuGK0Tj/ESVRs6yzkuHRnGIqPB92qzhg8yp62UMAAAAA=='; // Decode base64 (convert ascii to binary) var strData = atob(b64Data); // Convert binary string to character-number array var charData = strData.split('').map(function(x){return x.charCodeAt(0);}); // Turn number array into byte-array var binData = new Uint8Array(charData); // Pako magic var data = pako.inflate(binData); // Convert gunzipped byteArray back to ascii string: var strData = String.fromCharCode.apply(null, new Uint16Array(data)); // Output to console console.log(strData); |
正在运行的示例:http://jsfiddle.net/9yH7M/1/
有关更多高级功能,请阅读pako API文档。
使用高压缩级别的gzip-js lib
https://github.com/beatgammit/gzip-js
1 2 3 4 5 6 7 8 9 | var gzip = require('gzip-js'), options = { level: 9, name: 'hello-world.txt', timestamp: parseInt(Date.now() / 1000, 10) }; // out will be a JavaScript Array of bytes var out = gzip.zip('Hello world', options); |
我发现这种方式在正常持续时间下尽可能最小
对于基于LZ的压缩算法,我认为lz-string更快
检查您的数据样本
https://github.com/pieroxy/lz-string