*“高效”这里基本上意味着更小的尺寸(减少IO等待时间),以及快速的检索/反序列化时间 . 存储时间并不重要 .
我必须在浏览器的localStorage中存储几十个整数数组,每个数组都有0到50的范围内的1800个值 - 也就是说,作为一个字符串 .
显然,最简单的方法是,只是考虑到数据的范围是众所周知的,它会增加许多不必要的信息 . 这些数组之一的平均大小为~5500字节 .
以下是我尝试过的其他一些方法(结果大小,以及最后反序列化1000次的时间)
- 零填充数字,因此每个长度为2个字符,例如:
[5, 27, 7, 38] ==> "05270738"
- base 50对它进行编码:
[5, 11, 7, 38] ==> "5b7C"
- 只使用该值作为字符代码(添加32以避免开始时奇怪的控制字符):
[5, 11, 7, 38] ==> "%+'F" (String.fromCharCode(37), String.fromCharCode(43) ...)
这是我的结果:
size Chrome 18 Firefox 11
-------------------------------------------------
JSON.stringify 5286 60ms 99ms
zero-padded 3600 354ms 703ms
base 50 1800 315ms 400ms
charCodes 1800 21ms 178ms
我的问题是,如果有一个更好的方法,我还没有考虑过?
Update
MДΓΓБДLL建议对数据使用压缩 . Combining this LZW implementation使用基数50和charCode数据 . 我还测试了aroth的代码(将4个整数打包成3个字节) . 我得到了这些结果:
size Chrome 18 Firefox 11
-------------------------------------------------
LZW base 50 1103 494ms 999ms
LZW charCodes 1103 194ms 882ms
bitpacking 1350 2395ms 331ms
3 回答
您可能需要考虑使用
Uint8Array
或ArrayBuffer
. This blogpost显示了它如何's done. Copying his logic, here'是一个例子,假设你有一个名为arr
的现有Uint8Array
.如果您的范围是0-50,那么您可以将4个数字打包成3个字节(每个数字6位) . 这将允许您使用~1350字节存储1800个数字 . 这段代码应该这样做:
这是一个简单的例子:http://jsfiddle.net/NWyBx/1
请注意,通过对结果字符串应用gzip压缩,可以进一步降低存储大小 .
或者,如果您的数字排序不重要,那么您可以使用51个桶进行桶式排序(假设0-50包括0和50作为有效数字)并存储每个桶的计数而不是数字本身 . 这可能会比任何其他方法更好地提供压缩和效率 .
假设(如在你的测试中)压缩花费的时间比减小尺寸所节省的时间多,你的char编码是没有位移的最小值 . 您当前正在为每个数字使用一个字节,但如果它们保证足够小,则可以在每个字节中放置两个数字 . 这可能是一种过度优化,除非这是你的代码中非常热门的一部分 .