【问题标题】:Javascript Object Big-OJavascript 对象大 O
【发布时间】:2015-04-04 11:25:40
【问题描述】:

来自 Java,Javascript 对象让我想起了 Java 中的 HashMap。

Javascript:

var myObject = {
    firstName: "Foo",
    lastName: "Bar",
    email: "foo@bar.com"
};

Java:

HashMap<String, String> myHashMap = new HashMap<String, String>();
myHashMap.put("firstName", "Foo");
myHashMap.put("lastName", "Bar");
myHashMap.put("email", "foo@bar.com");

在 Java HashMap 中,它使用 key 的 hashcode() 函数来确定存储和检索的存储桶位置(条目)。在大多数情况下,对于 put() 和 get() 等基本操作,性能是恒定的,直到发生哈希冲突,对于这些基本操作而言这变成 O(n),因为它形成了一个链表来存储冲突的条目。

我的问题是:

  1. Javascript 是如何存储对象的?
  2. 运营绩效如何?
  3. 是否会出现任何冲突或其他会降低性能的情况,如 Java 中

谢谢!

【问题讨论】:

  • 看看这个链接,它有一些关于你的问题的好信息:github.com/benblack86/java-snippets/blob/master/resources/…
  • @EvanBechtol 那篇论文是关于 Java 的,而这个问题是关于 JavaScript 性能的。
  • 对象存储依赖于实现。也就是说,这个问题可以针对 v8 和 spidermonkey 来回答,但这些都是很长的答案。
  • 这个问题在 Java 标签下。不管怎样,这对 JS 来说是一个很好的资源 javascript.crockford.com/survey.html stackoverflow.com/questions/7374171/…
  • 好问题!不幸的是,答案取决于实现。基本上,所有的 js 对象处理都是 O(1)。 v8(Chrome 的引擎)首先为您的对象创建一个结构,从而为您提供最快的访问。一旦超过键计数,它就会退回到基本的哈希表模式。更多关于 here.

标签: javascript performance big-o


【解决方案1】:

Javascript 看起来像是在地图中存储东西,但通常情况并非如此。您可以像访问映射中的索引一样访问对象的大多数属性,并在运行时分配新属性,但支持代码比仅使用映射要快得多且复杂得多。

没有什么要求 VM 不使用映射,但大多数尝试检测对象的结构并为该结构创建有效的内存表示。这可能会在程序运行时导致大量优化(和 deopts),这是一个非常复杂的情况。

@Zirak 在问题 cmets 中链接的This blog post 对常见结构以及 VM 何时可以从结构切换到映射进行了很好的讨论。它通常看起来不可预测,但主要基于 VM 中的一组启发式方法以及它认为它已经看到了多少不同的对象。这在很大程度上与返回值的属性(及其类型)有关,并且往往以每个函数(尤其是构造函数)为中心。

有一些深入细节的问题和文章(但希望在没有大量背景的情况下仍然可以理解):

根据上述情况,性能差异很大。最坏的情况应该是映射访问,最好的情况是直接内存访问(甚至可能是 deref)。

有大量的场景可能会对性能产生影响,尤其是考虑到 JITter 和 VM 在运行时创建和销毁隐藏类的方式,因为它们会看到对象的新变化。突然遇到一个以前被认为是单态的对象的新变体可能会导致 VM 切换回不太理想的表示并停止将对象视为内存结构,但围绕它的逻辑非常复杂且很好-覆盖在this blog post

您可以确保从同一个构造函数创建的对象往往具有非常相似的结构,并使事情尽可能可预测(对您、维护和虚拟机都有好处),从而提供帮助。知道每个对象的属性,为这些属性设置类型,并在可能的情况下从构造函数创建对象,这样您就可以实现大多数可用的优化,并编写一些非常快速的代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-15
    • 1970-01-01
    • 2017-02-17
    • 2011-12-21
    • 2016-09-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多