19

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

2 回答 2

15

您的工作是基于一个基本假设,即 Javascript 中的对象与 C++ 中的对象一样工作。他们没有。

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

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

JavaScript 实现可以随意分配内存,而且你在源代码中所做的任何事情与机器中实际完成的事情之间没有对应关系。

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

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

于 2014-07-30T17:28:40.183 回答
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 中进行测试

于 2014-07-30T16:06:16.350 回答