【问题标题】:Performance of large maps in ClojureClojure 中大型地图的性能
【发布时间】:2011-09-12 06:29:52
【问题描述】:

我有一个 Clojure 程序,它使用一些大型地图(1000 - 2000 个项目),每秒访问 30 - 40 次,并使用字符串作为键。我想知道如果我使用关键字或符号作为键,是否会有很大的性能差异?

【问题讨论】:

  • 我敢打赌,您可以通过在 REPL 上亲自尝试来更快、更准确地找到答案,而不是等待 SO 上的答案。
  • 这是个好主意。我该怎么做?
  • 如果我说:“使用符号是性能提升”,你会怎么做,你将这样的代码投入生产并遭受降级?你会指责我吗? :) 请自己试一试,很简单——几行代码
  • 有没有“少”行代码的版本?

标签: clojure


【解决方案1】:

Clojure 地图查找速度非常快,而且并不特别依赖于地图的大小。

事实上,它们几乎与纯 Java HashMap 一样快,同时享有许多优于传统 HashMap 的优势,包括不可变和线程安全。

如果您每秒只进行 30-40 次查找,那么我保证 无论您使用什么作为键,您都不会注意到差异。担心这一点会被视为过早的优化。

让我们证明一下:以下代码使用字符串作为键进行了一百万次地图查找:

(def str-keys (map str (range 1000)))
(def m (zipmap str-keys (range 1000)))
(time (dotimes [i 1000] (doseq [k str-keys] (m k))))
=> "Elapsed time: 69.082224 msecs"

以下使用关键字作为键进行一百万次地图查找:

(def kw-keys (map #(keyword (str %)) (range 1000)))
(def m (zipmap kw-keys (range 1000)))
(time (dotimes [i 1000] (doseq [k kw-keys] (m k))))
=> "Elapsed time: 59.212864 msecs"

对于符号:

(def sym-keys (map #(symbol (str %)) (range 1000)))
(def m (zipmap sym-keys (range 1000)))
(time (dotimes [i 1000] (doseq [k sym-keys] (m k))))
=> "Elapsed time: 61.590925 msecs"

在我的测试中,Symbols 和 Keywords 比 Strings 稍快,但仍然可以很容易地用统计错误来解释差异,并且在所有情况下,每次查找的平均执行时间都小于 100 纳秒 .

因此,您的 30-40 次查找可能会占用您 CPU 时间的 0.001%(这甚至考虑到在实际应用中,由于缓存问题,查找可能会慢几倍)

特别是关键字稍微快一些的可能原因是它们被实习(因此可以使用引用相等来检查相等)。但正如您所看到的,差异非常小,您真的不需要担心。

【讨论】:

  • 嗯,为了记录,我用 ClojureScript REPL 运行了这些,得到:str-keys:62 毫秒,kw-keys:90 毫秒,sym-keys:59 毫秒.. 恕我直言,现在很好,想知道这是否真的是 JavaScript。
  • 符号不能使用引用相等来测试相等:((juxt identical? =) 'a 'a) => [false true]
  • @amalloy - 哈哈,我认为 Symbol.intern 实际上是对符号进行了实习,但显然它没有:-) 答案已编辑。但知道为什么它不实习吗?这是 Clojure 实现的错误吗?
  • @mikera:不,这是设计使然:“相同”符号的两个副本可以保存不同的元数据。但是,符号的 names 是内部的,因此符号相等性比引用相等性测试多一点工作(提取字符串 - 每个符号两个:命名空间和名称 - 然后测试引用相等性;嗯,严格来说,首先尝试“整个对象”引用相等性检查,然后是 instanceof 检查,以便符号永远不等于非符号;3x ==,1x instanceof和 2x 字段访问最大值以确定两个符号是否相等(如果相等)。
  • 啊,这完全有道理 - 感谢 Michal 一如既往的启发性解释!
猜你喜欢
  • 2013-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多