Javascript中的内存布局 - 面向数据与面向对象的设计

时间:2014-07-30 15:46:59

标签: javascript oop memory-layout data-oriented-design

来自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];

2 个答案:

答案 0 :(得分:10)

你从一个基本的假设开始工作,即Javascript中的对象就像在C ++中一样工作。他们没有。

在C ++中,一种类型的主要目的是充当"镜头"超过一大块记忆。类布局以明确定义的方式直接定义对象描述的内存的内容。 C / C ++数组特别需要线性连续的同类型布局。

在JavaScript中,对象是名称/值对的集合。数组只是一个特殊的"长度"属性。请注意,这里没有关于存储器布局的描述或定义。没有什么能阻止Javascript解释器将数组实现为哈希表而不是线性内存块;事实上,我确信他们是JS实现就是这样。

JavaScript实现可以自由地布置内存,但是在源代码中执行的任何内容与实际在机器中实际结束的内容之间都没有对应关系。

此外,JavaScript数组是异构的,而不是同类的。也就是说,假设它是在连续的内存中布局的,你在C中的等价类型将是JSObject **,而不是int **(或浮动**或其他)。 JS数组是对其他地方存储的数据的引用的集合,因此即使引用位于缓存行中,您的数据也不会。

所以,总而言之 - 这种想法只会给你带来痛苦。 JavaScript是一种比C ++更高级的语言,其中一部分是放弃了你习惯的控制。如果可能的话,这种低级优化将由解释器完成。专注于使用自然表达解决方案的高效算法编写代码;这很难。 : - )

答案 1 :(得分:5)

确定。摆弄一些数字和测试用例..

首先,我创建了此测试用例 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中进行测试