2024 Clojure状态调查!分享您的想法。

欢迎!请参见关于页面了解更多这方面的信息。

0
集合

c.c/hash始终使用hashCode为Java集合创建哈希,在与使用Murmur3的Clojure集合进行比较时不兼容。

user=> (== (hash (java.util.ArrayList. [1 2 3])) (hash [1 2 3])) false user=> (= (java.util.ArrayList. [1 2 3]) [1 2 3]) true

修复此问题的一种方法是在Util/hasheq中为java.util.Collections添加一个特殊情况,就像现在为String那样。

有关这个主题在Clojure小组的讨论链接: https://groups.google.com/forum/#!topic/clojure/dQhdwZsyIEw

43 个答案

0

stu发表的评论:

我认为这个问题需要更多的考虑,并且不应该阻止1.6版本。

0

jafingerhut发表的评论:

截至2014年3月20日的最新Clojure master,两个补丁clj-1372.diff和clj-1372-2.diff未能干净地应用。我相信它们在2014年3月19日的提交之前可以干净地应用,唯一的问题是差异上下文的变化行。鉴于关于是否需要此类更改的讨论,似乎在决定是否需要进行更改之前需要更多的思考。

0

mikera发表的评论:

这是一个相当严重的缺陷。绝对需要修复它。这并不是关于混合使用Clojure和Java集合是否是一个可能的用例的问题(可能不是...),而是关于提供人们可以依赖的一致保障。

例如,我现在对一些使用集合或映射的库函数是否损坏确实感到不确定。我尤其担心任何基于哈希值的对象缓存/记忆化/内部化的实现。这样的代码现在可能存在一些真正讨厌的微妙缺陷。

由于它们是库函数,我无法保证传入的对象类型,因此代码必须适用于所有可能的输入(或者我需要编写一个清晰的文档字符串,并在输入不受支持时抛出异常)。

0
_评论者:michalmarczyk_

这个补丁(0001-CLJ-1372-consistent-hasheq-for-java.util.-List-Map-M.patch)使得hasheq对java.util.{List,Map,Map.Entry,Set}保持一致性。它还扩展了对String的特殊处理(返回hashCode的hasheq)到所有未处理的其他类型(详见下文对此的评论)。

它也在这里可用

https://github.com/michalmarczyk/clojure/tree/alien-hasheq-2

更早的版本在这里可用

https://github.com/michalmarczyk/clojure/tree/alien-hasheq

如果我的理解正确,需要基准测试的主要是Clojure类型给clojure.lang.Util/hasheq的“分发时间”。因此,我重复多次对同一个持久性哈希映射进行哈希,从理论上讲,这将仅测量IHashEq实例上的分发时间。然后我运行了一个独立的基准测试来对PHM、一个字符串和一个长整数进行哈希,并使用unchecked-add将结果相加。希望这是一个良好的开始;我无疑认为额外的基准测试也会很有用。

结果让我有些惊讶:PHM上的hasheq在这个基准测试中比1.6.0快一点;"添加三个hasheq"基准测试在1.6.0上略快。


;;; 1.6.0

;;; 注意:j.u.HM基准不相关
user=> (let [phm (apply hash-map (interleave (range 128) (range 128))) juhm (java.util.HashMap. phm)] #_(assert (= (hash phm) (hash juhm))) (c/bench (clojure.lang.Util/hasheq phm)) (c/bench (clojure.lang.Util/hasheq juhm)))
WARNING: 最后的GC需要1.24405836928592 %的运行时
评估计数:5549560980在60个样本的92492683次调用中。
             执行时间平均值:9.229881 ns
    执行时间标准偏差:0.156716 ns
   执行时间下四分位数:8.985994 ns ( 2.5%)
   执行时间上四分位数:9.574039 ns (97.5%)
                   开销使用:1.741068 ns

在60个样本中发现了2个异常值(3.3333%)
    低严重      2 (3.3333%)
 异常值方差:6.2652 % 异常值导致方差略有膨胀
评估计数:35647680在60个样本的594128次调用中。
             执行时间平均值:1.695145 µs
    执行时间标准偏差:20.186554 ns
   执行时间下四分位数:1.670049 µs ( 2.5%)
   执行时间上四分位数:1.740329 µs (97.5%)
                   开销使用:1.741068 ns

在60个样本中发现了2个异常值(3.3333%)
    低严重      2 (3.3333%)
 异常值方差:1.6389 % 异常值导致方差略有膨胀
nil

用户=> (let [phm (apply hash-map (interleave (range 128) (range 128))) juhm (java.util.HashMap. phm)] 最终GC所需时间占1.028614538339401%的运行时间
警告:最终GC所需占1.028614538339401 %的运行时间
评估次数:在60个样本中的17165805次调用中为1029948300次。
             执行时间平均值:56.797488 ns
    执行时间标准差:0.732221 ns
   执行时间下四分位数:55.856731 ns(2.5%)
   执行时间上四分位数:58.469940 ns(97.5%)
                   开销使用:1.836671 ns

在60个样本中找到1个异常值(1.6667%)
    低严重程度     1(1.6667%)
 异常值方差:1.6389 % 异常值导致方差略有膨胀
nil

;;修补程序应用

用户=> (let [phm (apply hash-map (interleave (range 128) (range 128))) juhm (java.util.HashMap. phm)] (assert (= (hash phm) (hash juhm))) (c/bench (clojure.lang.Util/hasheq phm)) (c/bench (clojure.lang.Util/hasheq juhm)))
评估次数:在60个样本中的92294978次调用中为5537698680次。
             执行时间平均值:8.973200 ns
    执行时间标准差:0.157079 ns
   执行时间下四分位数:8.733544 ns(2.5%)
   执行时间上四分位数:9.289350 ns(97.5%)
                   开销使用:1.744772 ns
评估次数:在60个样本中的41360次调用中为2481600次。
             执行时间平均值:24.287800 µs
    执行时间标准差:288.124326 ns
   执行时间下四分位数:23.856445 µs(2.5%)
   执行时间上四分位数:24.774097 µs(97.5%)
                   开销使用:1.744772 ns
nil

用户=> (let [phm (apply hash-map (interleave (range 128) (range 128))) juhm (java.util.HashMap. phm)] 最终GC所需时间占1.028614538339401%的运行时间
警告:最终GC所需占1.298136122909759 %的运行时间
评估次数:在60个样本中的15912525次调用中为954751500次。
             执行时间平均值:61.681794 ns
    执行时间标准差:0.712110 ns
   执行时间下四分位数:60.622003 ns(2.5%)
   执行时间上四分位数:62.904801 ns(97.5%)
                   开销使用:1.744772 ns

在60个样本中找到1个异常值(1.6667%)
    低严重程度     1(1.6667%)
 异常值方差:1.6389 % 异常值导致方差略有膨胀
nil


顺便提一下,另一个分支上可用的较早版本的补丁没有为String单独创建分支。这使得对实现IHashEq的对象的hasheq更快,但将“三个散列”基准测试的速度慢了约2倍。
0

评论者:alexmiller

为了清晰起见,请按照名称引用此处附上的补丁,以便随着时间的推移,我们不必将附件时间与评论时间关联起来。

我对实现IHashEq的事物不太担忧它们的成本,因为它们应该不会受影响,除了可能存在的内联问题。我对以下事物的hasheq成本感到好奇,这些事物最终会落到cases的末端并支付所有检查的成本。上方的注释列表是一个很好的起点——例如,类、字符和Var(这些可能在Var中得到解决)。

0

评论由:michalmarczyk 发表

好的观点,我已经编辑上面评论,加入了补丁名称。

感谢对基准测试的建议——我将在大约6分钟后发布一些新结果。

0

评论由:michalmarczyk 发表

首先,为了完整性,这里有一个新的补丁(0001-CLJ-1372-consistent-hasheq-for-java.util.-List-Map-M-alternative.patch),该补丁对于未另外处理的类型不会进行额外咕哝(murmuring)。单 PHM 案例中运行较慢;详细信息请见下文。此外,这里是 GitHub 上的分支

https://github.com/michalmarczyk/clojure/tree/alien-hasheq-3

至于新的结果,性能损失相当大,我担心

`
;;; 与补丁(murmur hashCode 默认版本)相比
user=> (let [class-instance java.lang.String character-instance \a var-instance #'hash] (c/bench (clojure.lang.Util/hasheq class-instance)) (c/bench (clojure.lang.Util/hasheq character-instance)) (c/bench (clojure.lang.Util/hasheq var-instance)))
警告:最终 GC 需要 1.409118084170768 % 的运行时间
评估计数:655363680 在 60 个样本中,每个样本 10922728 次。

         Execution time mean : 96.459888 ns
Execution time std-deviation : 1.019817 ns

执行时间下四分位数:95.079086 纳秒(2.5%)
执行时间上四分位数:98.684168 纳秒(97.5%)

               Overhead used : 1.708347 ns

评估计数:675919140 在 60 个样本中,每个样本 11265319 次。

         Execution time mean : 88.965959 ns
Execution time std-deviation : 0.825226 ns

执行时间下四分位数:87.817159 纳秒(2.5%)
执行时间上四分位数:90.755688 纳秒(97.5%)

               Overhead used : 1.708347 ns

评估计数:574987680 在 60 个样本中,每个样本 9583128 次。

         Execution time mean : 103.881498 ns
Execution time std-deviation : 1.103615 ns

执行时间下四分位数:102.257474 纳秒(2.5%)
执行时间上四分位数:106.071144 纳秒(97.5%)

               Overhead used : 1.708347 ns

在60个样本中找到1个异常值(1.6667%)

low-severe	 1 (1.6667 %)

异常值方差:1.6389 % 异常值导致方差略微膨胀
nil

;;; 1.6.0
user=> (let [class-instance java.lang.String character-instance \a var-instance #'hash] (c/bench (clojure.lang.Util/hasheq class-instance)) (c/bench (clojure.lang.Util/hasheq character-instance)) (c/bench (clojure.lang.Util/hasheq var-instance)))
警告:最终 GC 需要 1.3353133083866688 % 的运行时间
评估计数:1829305260 在 60 个样本中,每个样本 30488421 次。

         Execution time mean : 34.205701 ns
Execution time std-deviation : 0.379106 ns

执行时间下四分位数:33.680636 纳秒(2.5%)
执行时间上四分位数:34.990138 纳秒(97.5%)

               Overhead used : 1.718257 ns

在60个样本中发现了2个异常值(3.3333%)

low-severe	 1 (1.6667 %)
low-mild	 1 (1.6667 %)

异常值方差:1.6389 % 异常值导致方差略微膨胀
评估计数:1858100340 在 60 个样本中,每个样本 30968339 次。

         Execution time mean : 30.401309 ns
Execution time std-deviation : 0.213878 ns

执行时间下四分位数:30.095976 纳秒(2.5%)
执行时间上四分位数:30.871497 纳秒(97.5%)

               Overhead used : 1.718257 ns

评估计数:1592932200 在 60 个样本中,每个样本 26548870 次。

         Execution time mean : 36.292934 ns
Execution time std-deviation : 0.333512 ns

执行时间下四分位数:35.795063 纳秒(2.5%)
执行时间上四分位数:36.918183 纳秒(97.5%)

               Overhead used : 1.718257 ns

在60个样本中找到1个异常值(1.6667%)

low-severe	 1 (1.6667 %)

异常值方差:1.6389 % 异常值导致方差略微膨胀
nil
`

使用新补丁(默认情况下无额外 murmur 步骤)的单 PHM 和 Class/Character/Var 结果

`
用户=> (let [phm (apply hash-map (interleave (range 128) (range 128))) juhm (java.util.HashMap. phm)] 最终GC所需时间占1.028614538339401%的运行时间
警告:最终 GC 需要 1.258952964663877 % 的运行时间
评估计数:1007768460 在 60 个样本中,每个样本 16796141 次。

         Execution time mean : 58.195608 ns
Execution time std-deviation : 0.482804 ns

执行时间下四分位数:57.655857 纳秒(2.5%)
执行时间上四分位数:59.154655 纳秒(97.5%)

               Overhead used : 1.567532 ns

在60个样本中找到1个异常值(1.6667%)

low-severe	 1 (1.6667 %)

异常值方差:1.6389 % 异常值导致方差略微膨胀
nil
user=> (let [class-instance java.lang.String character-instance \a var-instance #'hash] (c/bench (clojure.lang.Util/hasheq class-instance)) (c/bench (clojure.lang.Util/hasheq character-instance)) (c/bench (clojure.lang.Util/hasheq var-instance)))
评估计数:647944080 在 60 个样本中,每个样本 10799068 次。

         Execution time mean : 91.275863 ns
Execution time std-deviation : 0.659943 ns

执行时间下四分位数:90.330980 纳秒(2.5%)
执行时间上四分位数:92.711120 纳秒(97.5%)

               Overhead used : 1.567532 ns

评估计数:699506160 在 60 个样本中,每个样本 11658436 次。

         Execution time mean : 84.564131 ns
Execution time std-deviation : 0.517071 ns

执行时间下四分位数:83.765607 纳秒(2.5%)
执行时间上四分位数:85.569206 纳秒(97.5%)

               Overhead used : 1.567532 ns

在60个样本中找到1个异常值(1.6667%)

low-severe	 1 (1.6667 %)

异常值方差:1.6389 % 异常值导致方差略微膨胀
评估计数:594919980 在 60 个样本中,每个样本 9915333 次。

         Execution time mean : 100.336792 ns
Execution time std-deviation : 0.811312 ns

执行时间下四分位数:99.313490 纳秒(2.5%)
执行时间上四分位数:102.167675 纳秒(97.5%)

               Overhead used : 1.567532 ns

在 60 个样本中发现 3 个异常值(5.0000 %)

low-severe	 3 (5.0000 %)

异常值方差:1.6389 % 异常值导致方差略微膨胀
nil
`

0

评论由:michalmarczyk 发表

这是一个新的补丁(0001-CLJ-1372-consistent-hasheq-for-java.util.-List-Map-M-substring.patch),它采取了替代 Iterable/Map/Entry 测试的极端方法,即在类名上使用 .startsWith("java.util.")。 (我曾尝试使用 .getClass().getPackage(),但其性能非常糟糕。)分支在这里

https://github.com/michalmarczyk/clojure/tree/alien-hasheq-4

这个补丁在 "fall-through" 情况下的哈希性能似乎非常好

`
user=> (let [class-instance java.lang.String character-instance \a var-instance #'hash] (c/bench (clojure.lang.Util/hasheq class-instance)) (c/bench (clojure.lang.Util/hasheq character-instance)) (c/bench (clojure.lang.Util/hasheq var-instance)))
警告:最终 GC 需要 1.31690036780011 % 的运行时间
评估计数:在 27690894 次调用中的 60 个样本,共 1661453640。

         Execution time mean : 35.099750 ns
Execution time std-deviation : 0.422800 ns

执行时间下四分位数:34.454839 纳秒(2.5%)
执行时间上四分位数:35.953584 纳秒(97.5%)

               Overhead used : 1.556642 ns

评估计数:在 27169460 次调用中的 60 个样本,共 1630167600。

         Execution time mean : 35.487409 ns
Execution time std-deviation : 0.309872 ns

执行时间下四分位数:35.083030 纳秒(2.5%)
执行时间上四分位数:36.190015 纳秒(97.5%)

               Overhead used : 1.556642 ns

发现了 60 个样本中的 4 个异常值(6.6667 %)

low-severe	 3 (5.0000 %)
low-mild	 1 (1.6667 %)

异常值方差:1.6389 % 异常值导致方差略微膨胀
评估计数:在 24007245 次调用中的 60 个样本,共 1440434700。

         Execution time mean : 40.894457 ns
Execution time std-deviation : 0.529510 ns

执行时间下四分位数:40.055991 纳秒(2.5%)
执行时间上四分位数:41.990985 纳秒(97.5%)

               Overhead used : 1.556642 ns

nil
`

0
_评论者:michalmarczyk_

新补丁(...-substring.patch)返回除了 List、Map、Map.Entry 和 Set 之外的 java.util.** 类的 hashCode,当然,所以这部分没有行为变化。

以下是重复 PHM 查询的性能基准(比 1.6.0 略慢,但均在 1 纳秒以内)以及 "添加三个 hasheqs" 基准(有补丁 66 纳秒,无补丁 57 纳秒)


用户=> (let [phm (apply hash-map (interleave (range 128) (range 128))) juhm (java.util.HashMap. phm)] (assert (= (hash phm) (hash juhm))) (c/bench (clojure.lang.Util/hasheq phm)) (c/bench (clojure.lang.Util/hasheq juhm)))
评估计数:在 86397354 次调用中的 60 个样本,共 5183841240。
             平均执行时间:10.076893 纳秒
    标准偏差:0.182592 纳秒
   下四分位数:9.838456 纳秒(2.5%)
   上四分位数:10.481086 纳秒(97.5%)
                 开销:1.565749 纳秒
评估计数:在 51507 次调用中的 60 个样本,共 3090420。
             平均执行时间:19.596627 微秒
    标准偏差:224.380257 纳秒
   下四分位数:19.288347 微秒(2.5%)
   上四分位数:20.085620 微秒(97.5%)
                 开销:1.565749 纳秒
nil

用户=> (let [phm (apply hash-map (interleave (range 128) (range 128))) juhm (java.util.HashMap. phm)] 最终GC所需时间占1.028614538339401%的运行时间
警告:最终 GC 需要 1.418253438197936 % 的运行时间
评估计数:在 14653515 次调用中的 60 个样本,共 879210900。
             平均执行时间:66.939309 纳秒
    标准偏差:0.747984 纳秒
   下四分位数:65.667310 纳秒(2.5%)
   上四分位数:68.155046 纳秒(97.5%)
                 开销:1.724002 纳秒
nil


需要注意的是,我在测试 1.6.0 时获得了 "三个 hasheqs" 基准的无补丁结果,因此也是这样在有补丁的情况下重复基准测试的。许多不同类型的哈希会明显改变结果--大概是因为 HotSpot 在看到多个不同类型传入 hasheq 后,退回了一些优化?
0

评论由:michalmarczyk 发表

这是一个新的补丁(0005-CLJ-1372-consistent-hasheq-for-java.util.-List-Map-M.patch),它引入了一个名为isAlien的静态方法,用于检查实例是否为Map/Map.Entry/Iterable,并使用此方法来测试“异物集合”。

初步基准测试结果令人鼓舞

`
;;; “贯穿”基准测试
user=> (let [class-instance java.lang.String character-instance \a var-instance #'hash] (c/bench (clojure.lang.Util/hasheq class-instance)) (c/bench (clojure.lang.Util/hasheq character-instance)) (c/bench (clojure.lang.Util/hasheq var-instance)))
警告:最后的GC需要运行时的1.258979068087473 %
评估次数:在60个样本中的26640535次调用,总数为1598432100。

         Execution time mean : 36.358882 ns
Execution time std-deviation : 0.566925 ns

执行时间下四分位数:35.718889纳秒(2.5%)
执行时间上四分位数:37.414722纳秒(97.5%)

               Overhead used : 1.823120 ns

在60个样本中找到1个异常值(1.6667%)

low-severe	 1 (1.6667 %)

异常值方差:1.6389 % 异常值导致方差略微膨胀
评估次数:在60个样本中的27106041次调用,总数为1626362460。

         Execution time mean : 35.426993 ns
Execution time std-deviation : 0.294517 ns

执行时间下四分位数:35.047064纳秒(2.5%)
执行时间上四分位数:36.058667纳秒(97.5%)

               Overhead used : 1.823120 ns

在60个样本中找到1个异常值(1.6667%)

low-severe	 1 (1.6667 %)

异常值方差:1.6389 % 异常值导致方差略微膨胀
评估次数:在60个样本中的24357053次调用,总数为1461423180。

         Execution time mean : 39.541873 ns
Execution time std-deviation : 0.423707 ns

执行时间下四分位数:38.943560纳秒(2.5%)
执行时间上四分位数:40.499433纳秒(97.5%)

               Overhead used : 1.823120 ns

在60个样本中发现了2个异常值(3.3333%)

low-severe	 2 (3.3333 %)

异常值方差:1.6389 % 异常值导致方差略微膨胀
nil

;;; “三个hasheq”基准测试
用户=> (let [phm (apply hash-map (interleave (range 128) (range 128))) juhm (java.util.HashMap. phm)] 最终GC所需时间占1.028614538339401%的运行时间
警告:最后的GC需要运行时的1.5536755331464491 %
评估次数:在60个样本中的13672941次调用,总数为820376460。

         Execution time mean : 71.999365 ns
Execution time std-deviation : 0.746588 ns

执行时间下四分位数:70.869739纳秒(2.5%)
执行时间上四分位数:73.565908纳秒(97.5%)

               Overhead used : 1.738155 ns

在60个样本中发现了2个异常值(3.3333%)

low-severe	 2 (3.3333 %)

异常值方差:1.6389 % 异常值导致方差略微膨胀
nil
`

0
_评论者:michalmarczyk_

我忘记将重复的phm hasheq查找和java.util.HashMap实例对基准测试包含在内,这里补充完整(不过没有意外)


用户=> (let [phm (apply hash-map (interleave (range 128) (range 128))) juhm (java.util.HashMap. phm)] (assert (= (hash phm) (hash juhm))) (c/bench (clojure.lang.Util/hasheq phm)) (c/bench (clojure.lang.Util/hasheq juhm)))
警告:最后的GC需要运行时的1.260853406580491 %
评估次数:在60个样本中的89485596次调用,总数为5369135760。
             平均执行时间:10.380464纳秒
    执行时间标准差:3.407284纳秒
   执行时间下四分位数:9.510624纳秒(2.5%)
   执行时间上四分位数:11.461485纳秒(97.5%)
                   开销:1.566301纳秒

在60个样本中发现了5个异常值(8.3333%)
    低-严重     3(5.0000%)
    低-轻微     2(3.3333%)
 与异常值的相关性:96.4408 % 异常值导致方差被严重扩大
评估次数:在60个样本中的51303次调用,总数为3078180。
             平均执行时间:19.717981微秒
    执行时间标准差:209.896848纳秒
   执行时间下四分位数:19.401811微秒(2.5%)
   执行时间上四分位数:20.180163微秒(97.5%)
                   开销:1.566301纳秒

在60个样本中发现了2个异常值(3.3333%)
    低严重      2 (3.3333%)
 异常值方差:1.6389 % 异常值导致方差略有膨胀
nil
0

评论者:alexmiller

请不要提交任何更改hashcode的补丁,除非是为了使Java集合与Clojure集合匹配 - 其他任何更改都不属于此问题的范围。

一般来说,目前我更倾向于只看执行时间的平均值报告,而不是所有的东西——完整的准则输出使得这些评论更难以阅读和比较。

0

评论者:alexmiller

能否给我一个不同方法的概述,以及1.6.0与每个补丁一致集的测试时间——比如Long、PHM、juHM、Class和"三个hasheq"测试的哈希时间?

0
_评论者:richhickey_

"对不同类型的哈希会导致结果明显变化——很可能是HotSpot在看到几个不同类型的hasheq输入后放弃了一些优化?"

没错——如果你的基准测试没有将这个站点视为Megamorphic,你将会得到各种扭曲的结果。
0
_评论者:michalmarczyk_

好,我认为这是一个改进的微基准测试:一个长整型、一个双精度浮点数、一个字符串、一个类、一个字符以及一个PHM(单个实例,因此它将是哈希查找)的hasheq的异或。结果并不令人鼓舞。

包含{{require}}以方便运行的单个形式;还包括一个{{j.u.HashMap}}(128条条目)的hasheq基准。


(do
  (require '[criterium.core :as c]))
  (let [l 41235125123]
    d 123.456]
    s "asdf;lkjh"]
    k BigInteger]
    c \S]
    phm (apply hash-map (interleave (range 128) (range 128)))]
    juhm (java.util.HashMap. phm)]
    f (fn f [])
        (-> (clojure.lang.Util/hasheq l)
             bit-xor (clojure.lang.Util/hasheq d))
            bit-xor (clojure.lang.Util/hasheq s))
            bit-xor (clojure.lang.Util/hasheq k))
            bit-xor (clojure.lang.Util/hasheq c))
            bit-xor (clojure.lang.Util/hasheq phm))]
    (c/bench (f))
    (c/bench (hash juhm))


Criterium报告的平均执行时间

||版本||xor (ns)||j.u.HM (µs)||
|未修补的1.6.0|148.128748|1.701640|
|0005修复程序|272.039667|21.201178|
|原始修复程序|268.670316|21.169436|
|-替代修复程序|271.747043|20.755397|

子串修复程序已损坏(见下文),所以跳过了。我描述为"原始"的补丁已附在0001-CLJ-1372-consistent-hasheq-for-java.util.-List-Map-M.patch中。

所有补丁共同的决定

1. 在默认返回值的上方的 {{hasheq}} 中有一额外的一个 {{if}} 语句,进行三向 {{instanceof}} 检查。

2. 测试的类型为 {{j.u.Iterable}}、{{j.u.Map.Entry}} 和 {{j.u.Map}}。

3. {{Murmur3.hashOrdered}} 接受 {{Iterable}} 类型,因此它出现在列表中。{{Map}} 不继承自 {{Iterable}},因此单独列出。{{Map.Entry}} 出现在列表中,因为计算哈希图的方法是迭代并哈希它们的条目。

4. “外星”/主类型的实际哈希操作是通过一个独立的静态方法完成的 -- {{clojure.lang.Util.doalienhasheq}} -- 假设这将允许 {{hasheq}} 更有效地内联,并将性能损失的最坏情况限制在外星集合上。

5. {{doalienhasheq}} 检查 {{Map}}、{{Map.Entry}}、{{Set}} 和 {{List}};条目被转换为列表进行哈希,地图通过条目集进行哈希,列表和集合直接传递给 {{Murmur3}}。

6. 对于其他 {{Iterable}} 类型还有默认情况 -- 我们必须为这些返回 {{hashCode}} 或将某些其他函数与 {{hashCode}} 组合的结果,因为我们使用 {{equals}} 来测试它们的等价性。

0005补丁让 {{hasheq}} 调用独立的私有静态方法来完成三向类型检查,而其他补丁将检查直接放在实际的 {{if}} 测试中。-alternative 补丁和 0005 补丁在默认情况下返回 {{hashCode}},而原始补丁将 {{Murmur3.hashInt}} 与 {{hashCode}} 组合。

子串补丁仅适用于 {{java.util.**}} 类,所以它不能解决问题(例如,它不会正确哈希 Guava 集合)。

所有补丁都更改了 {{c.l.Util.hasheq}} 并向 {{clojure.lang.Util}} 添加了一个或两个新的静态方法作为 {{hasheq}} 的辅助程序。它们都没有更改其他内容。Murmuring hashCode 是一个性能实验,似乎在“快速情况”中产生了一些轻微的正影响(事实上,在上述微基准测试中,它在当前三个补丁中仍然是最佳性能者,尽管胜利的差距当然非常小)。因此,我认为所有当前的补丁实际上都是针对与工单直接相关的更改;-alternative 补丁和 0005 补丁当然如此。
...