Javascript中的内存布局——面向数据vs面向对象设计

Memory layout in Javascript - data-oriented vs object-oriented design

本文关键字:数据 vs 面向对象设计 Javascript 内存 布局      更新时间:2023-09-26

从C/c++的背景来看,关于减少缓存丢失的对象的内存布局是至关重要的,特别是在主机上工作时。面向数据的设计通常比面向对象的设计更受青睐,以帮助在内存中保持相关对象彼此靠近(特别是在性能关键区域)。

最近,我一直在做一些Javascript开发,我想知道Javascript社区的普遍共识是什么。

以我有限的Javascript经验,我在分析时经常惊讶地看到完全意想不到的结果。Javascript对象/结构的内部内存布局和实现因浏览器而异,我想知道是否值得尝试优化。

我在jsPerf上创建了一个简单的测试用例(http://jsperf.com/object-vs-data)来比较这两种方法的性能,虽然它在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是一个高度发达的&高性能语言,你不应该担心这样的微优化。您应该关注的是语义。你应该选择最能描述你意图的结构。

Chrome 36.0.1985.125在Windows NT 6.3上的测试