在 JavaScript 中将小数字合并为一个是个好主意吗?(作为存储优化解决方案)
Is it a good idea to combine small numbers into one in JavaScript? (As a storage optimization solution)
据说
javascript 中的所有数字都是 64 位浮点数。
我想知道数字是否总是在内存中使用 64 位?
我有这样的数据结构(在 C 样式代码中(
{
int x; // [0-9]
int y; // [0-9]
int d; // [0-3]
}
x 和 y 将绝对在 [0-9] 范围内,d 的唯一可能值是 0、1、2、3。
如果我将它们存储为 3 位分隔的数字,结构会使用 64 位 * 3 = 192 位 = 24 字节吗?
如果是这样,我想将其存储在一个数字 x * 100 + y * 10 + d 中,这应该只使用 64 位(8 字节(。在不考虑 CPU 使用率的情况下,这更好吗?
我还考虑了字符串解决方案。
x.toString() + y.toString() + d.toString();
因为所有 x、y 和 d 都小于 10,所以它们应该只有 1 个字符,即 16 位。所以结构变成 16 位 * 3 = 48 位 = 6 字节。这是存储优化程度最高的解决方案吗?
那么mongoDB中的存储呢?如果我将数据结构存储到 mongoDB 中,情况是一样的吗?
我写了一个片段来测试mongo中的存储。最终结构包括上述结构的 3 个实例。总金额为66816。
我将它们存储到 3 个单独的数据库中:
- 布局满(我丢了一个's'(:一个数组包括 3 {x: valueX, y: valueY, d: valueD}
- layouts-int: xydxydxyd (十进制( ex. 233250750 表示 {x:2,y:3,d:3},{x:2,y:5,d:0},{x:7,y:5,d:0}
- layouts-str:将上面的 int 转换为 2 个字符的字符串。String.fromCharCode(i>> 16( + String.fromCharCode(i & 0xFFFF(
结果是...
> show dbs
layout-full 0.03125GB
layouts-int 0.03125GB
layouts-str 0.03125GB
但细节是...
布局完整的集合
"size" : 8017920,
"avgObjSize" : 120,
"storageSize" : 11182080,
布局中的集合-int
"size" : 2138112,
"avgObjSize" : 32,
"storageSize" : 5591040,
布局中的集合-str
"size" : 2405396,
"avgObjSize" : 36.000299329501914,
"storageSize" : 5591040,
从这些结果中,我发现int存储是最节省空间的方法。
我也这样做了:
> db.tiny.save({})
> db.tiny.stats().avgObjSize
24
> db.tiny.remove()
> db.tiny.save({l:null})
> db.tiny.stats().avgObjSize
28
> db.tiny.remove()
> db.tiny.save({l:[{x:null,y:null,d:null},{x:null,y:null,d:null},{x:null,y:null,d:null}]})
> db.tiny.stats().avgObjSize
84
因此,_id
将使用 24 个字节,而关键部分 {l:
将使用 4 = 28 - 24 个字节。
并且你可以发现一个整数使用 32 - 28 = 4 个字节,所以小于 2^31 的整数似乎在 mongo db 中存储为 32 位整数。
同样在字符串解决方案中,一个 2 个字符的字符串使用 36 - 28 = 8 个字节,刚好等于我猜的值。
而对于全结构解决方案,从上一个小数据库测试中,你可以看到没有数据的结构使用 84 个字节,所以数据使用 120 - 84 = 36 字节 = 9 * 4 字节。我的最终数据结构中只有 9 个整数(三重 x,y,d(。这也证明了整数存储为 32 位整数。
为什么空结构使用 84 个字节?
通过更多的实验,我发现 1 个数组或空 json 对象使用 4 个字节,一个键使用 * 4。
所以,空结构实际上是
{ // 1 object +4 bytes = 4
'_id': ObjectId('0123456789abcdef012345678'), // 3-char key + 12-byte id = 24
'l': [ // 1-char key + 1 array = 8
{'x': null, 'y': null, 'd': null}, // 1 object+ 3 keys = 16
{'x': null, 'y': null, 'd': null}, // 1 object+ 3 keys = 16
{'x': null, 'y': null, 'd': null} // 1 object+ 3 keys = 16
]
}
结果是 4 + 24 + 8 + 16 * 3 = 84 字节。
我希望我的实验对其他人有用。
这会将三个数字存储在一个字符字符串中。做得更好的唯一方法是使用类型化数组,但我不确定这是这里的一个选项。
function showMeSomeMagic(x, y, d) {
// we assume that:
// - x, y are integers in the range [0 9]
// - d is an integer in the range [0 3]
// if not add the appropriate checks/casting/coercing
var n = (d << 8) + (y << 4) + x;
// return a String made of a single Unicode code point in
// the range [0xE000 0xE399], i.e. inside the Unicode BMP PUA
return String.fromCharCode( n + 0xE000 );
}
function showMeSomeInverseMagic(s) {
// we assume that:
// s is a String created by showMeSomeMagic
var n = s.charCodeAt(0) - 0xE000;
var x = n & 15;
var y = (n >> 4) & 15;
var d = (n >> 8) & 15;
return { x:x, y:y, d:d };
}
编辑:根据OP评论更新
- 将脚本缓存到本地存储的basket.js概念仍然是一个好主意吗
- 使用每500ms运行一次的jquery函数是个好主意吗
- 在debounce函数中使用requestAnimationFrame是个好主意吗
- 通过进程使用 NodeJS 全局事件是个好主意吗?
- 将我所有的.js分组到一个文件中-好主意
- 与AMD共享库是个好主意吗
- 模块是打字的好主意吗?或者它们只是增加了复杂性
- 在Coffeescription中使用一个自调用函数来隐藏其余代码中的函数和变量,这是一个好主意吗
- 开发两个单独的节点应用程序来提供 Web 服务和使用 Web 服务以在浏览器上呈现它是一个好主意吗?
- Meteor:为集合服务器端创建筛选器,并将其存储在本地集合中.好主意
- 修改 yii.activeForm 是个好主意吗.js如果不是,另一种方法是什么
- Javascript中的异步类是一个好主意吗?
- 将 with-语句与上下文一起使用是个好主意吗?
- 在 JavaScript 中将小数字合并为一个是个好主意吗?(作为存储优化解决方案)
- 在第一次触摸启动事件时禁用所有点击事件是个好主意吗?
- 我可以定义一个函数来处理在 2 个输入标签上定义的“更改键控”事件吗?这是个好主意吗
- 使用经典继承,在 JavaScript 中使用“类级”/成员变量是一个好主意还是坏主意
- Cron Job是执行此任务的好主意吗?PHP
- 在JS模板中添加逻辑?好主意还是不行
- 在函数之外存储getElementById是个好主意吗?