Javascript 中的内存布局 - 面向数据与面向对象设计 [关闭]
-
21-12-2019 - |
题
由于具有 C/C++ 背景,对象的内存布局对于减少缓存未命中至关重要,尤其是在控制台上工作时。面向数据的设计通常比面向对象的设计更受青睐,以帮助保持相关对象在内存中彼此靠近(特别是在性能关键区域)。
最近,我一直在做一些 Javascript 开发,我想知道 Javascript 社区内的普遍共识是什么。
由于我在 Javascript 方面的经验有限,在分析时我经常惊讶地看到完全意想不到的结果。Javascript 对象/结构的内部内存布局和实现因浏览器而异,我想知道是否值得尝试优化。
我创建了一个简单的测试用例(http://jsperf.com/object-vs-data)在 jsPerf 上比较这两种方法的性能,虽然它在 Chrome 上显示出性能提升,但在 Safari 上没有明显的加速。
在 Javascript 中,我是否应该关心对象的内存布局?或者它更像是“以一种方式实现,然后根据需要进行优化”类型的事情?
第二种选择似乎有点浪费(就开发时间而言),特别是如果有一些好的指导原则可供遵循的话。
谢谢~
补充信息: :这基本上就是我在 Javascript 中实现这两种方法的方式。上面的jsPerf测试用例就是这样实现的。
var objectOriented = [
{ foo: 1, bar: 2 },
{ foo: 3, bar: 4 }
];
var dataOriented = {
foos: [1, 3],
bars: [2, 4]
};
// Object-oriented access:
var a = objectOriented[0].bar;
// Data-oriented access:
var b = dataOriented.bars[0];
解决方案
您的工作基于一个基本假设:Javascript 中的对象与 C++ 中的对象一样工作。他们不这样做。
在 C++ 中,类型的主要目的是充当内存块上的“镜头”。类布局以明确定义的方式直接定义对象描述的内存内容。C/C++ 数组特别需要同质类型的线性、连续布局。
在 JavaScript 中,对象是名称/值对的集合。数组只是一个具有特殊“长度”属性的对象。请注意,这里没有内存布局的描述或定义。没有什么可以阻止 Javascript 解释器将数组实现为哈希表而不是线性内存块;事实上,我确信它们是执行此操作的 JS 实现。
JavaScript 实现可以自由地按照它们想要的方式布局内存,并且您在源代码中执行的任何操作与机器中实际最终执行的操作之间没有对应关系。
此外,JavaScript 数组是异构的,而不是同质的。也就是说,假设它被放置在连续的内存中,那么 C 中的等效类型将是 JSObject **,而不是 int ** (或 float ** 或其他)。JS 数组是对存储在其他地方的数据的引用的集合,因此即使这些引用位于您的缓存行中,您的数据也不会。
所以,总而言之,这种想法只会给你带来痛苦。JavaScript 是一种比 C++ 高级得多的语言,其中一部分就是放弃您习惯的控制。如果可能的话,这种低级优化将由解释器完成。专注于使用高效算法编写代码,自然地表达您的解决方案;这已经够难的了。:-)
其他提示
好的。摆弄一些数字和测试用例..
首先我创建了这个测试用例 http://jsperf.com/object-vs-array-creation-for-so在这种情况下,创建 Object
是 更快 然后创建一个 Array
其次我创建了这个测试用例 http://jsperf.com/accessing-speed在这一点上,他们之间几乎没有任何区别。
因此,我从这个配置文件中推断出,如果项目是,使用比数组更多的对象会更快 真的很大..从第一种情况来看,很明显对象创建比数组创建更快。
但..
Javascript 是一种高度发达且高性能的语言,您不应该担心这种微观优化。您应该关注的只是 语义学. 。您应该选择最能描述您的意图的结构。
在 Windows NT 6.3 上的 Chrome 36.0.1985.125 中进行测试