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

欢迎!请参阅关于页面以了解更多有关如何使用此功能的信息。

0
Clojure
*说明*
有时需要将一组值与单个值进行比较,Clojure内部定义了用于此目的的谓词,该谓词相对于仅部分应用=具有一些不错的性能改进。

与Rich的先前讨论:https://groups.google.com/forum/#!topic/clojure-dev/0c-VNhEKVkI

*示例用法*

;;之前
(map (partial = 3) coll)
;;之后
(map (=to 3) coll)


*基准测试*

||test||(partial = 'foo)||#(= 'foo %)||(=to 'foo)||
|小型同质集合|217ns|165ns|39ns|
|小型异质集合,|192ns|167ns|41ns|
|大型同质集合|66us|52us|8us|
|大型异质集合|82us|66us|27us|

*完整基准测试输出*

(use 'criterium.core)

(defn benchmark-f [f]
  (let [colls [['foo 'foo 'foo]
               [1 :foo 'foo]
               (doall (repeat 1e3 'foo))
               (doall (take 1e3 (cycle [1 :foo 'foo])))]]
    (doseq [c colls]
      (quick-bench (run! f c)))))

(benchmark-f (partial = 'foo))
WARNING: Final GC required 1.405293826432628 % of runtime
WARNING: Final GC required 10.202923149112559 % of runtime
Evaluation count : 3116130 in 6 samples of 519355 calls.
Execution time mean : 217.723199 ns
Execution time std-deviation : 29.425291 ns
Execution time lower quantile : 189.944710 ns ( 2.5%)
Execution time upper quantile : 261.717351 ns (97.5%)
Overhead used : 1.863362 ns
WARNING: Final GC required 4.2579397621583315 % of runtime
Evaluation count : 3138636 in 6 samples of 523106 calls.
Execution time mean : 198.985418 ns
Execution time std-deviation : 12.691848 ns
Execution time lower quantile : 182.441245 ns ( 2.5%)
Execution time upper quantile : 207.839280 ns (97.5%)
Overhead used : 1.863362 ns
WARNING: Final GC required 6.631646134523004 % of runtime
Evaluation count : 10038 in 6 samples of 1673 calls.
Execution time mean : 66.977712 µs
Execution time std-deviation : 10.411821 µs
Execution time lower quantile : 59.620690 µs ( 2.5%)
Execution time upper quantile : 84.483254 µs (97.5%)
Overhead used : 1.863362 ns

Found 1 outliers in 6 samples (16.6667 %)
low-severe  1 (16.6667 %)
Variance from outliers : 47.3059 % Variance is moderately inflated by outliers
WARNING: Final GC required 5.272721959665122 % of runtime
Evaluation count : 7908 in 6 samples of 1318 calls.
Execution time mean : 82.588512 µs
Execution time std-deviation : 5.215537 µs
Execution time lower quantile : 75.977936 µs ( 2.5%)
Execution time upper quantile : 86.849982 µs (97.5%)
Overhead used : 1.863362 ns


(benchmark-f #(= 'foo %))
WARNING: Final GC required 1.284421364203217 % of runtime
WARNING: Final GC required 10.04376144830405 % of runtime
Evaluation count : 3643032 in 6 samples of 607172 calls.
             平均执行时间:165.393131 纳秒
    执行时间标准差:1.041355 纳秒
   执行时间下四分位数:164.277060 纳秒(2.5%)
   执行时间上四分位数:166.849951 纳秒(97.5%)
                     使用的开销:1.605524 纳秒
警告:最终垃圾收集器(GC)需要运行时的 6.258680973295933 %
评估次数:3584574 次在 6 个样本中的 597429 次调用。
             平均执行时间:167.659014 纳秒
    执行时间标准差:3.821817 纳秒
   执行时间下四分位数:164.175156 纳秒(2.5%)
   执行时间上四分位数:173.210781 纳秒(97.5%)
                     使用的开销:1.605524 纳秒

Found 1 outliers in 6 samples (16.6667 %)
    低严重程度     1(16.6667 %)
 异常值的影响差异:13.8889 % 异常值导致方差中度膨胀
警告:最终垃圾收集器(GC)需要运行时的 6.914389197005716 %
评估次数:11196 次在 6 个样本中的 1866 次调用。
             平均执行时间:52.593759 微秒
    执行时间标准差:834.220092 纳秒



(benchmark-f (=to 'foo))
警告:最终垃圾收集器(GC)需要运行时的 7.40391654943877 %
评估次数:15169068 次在 6 个样本中的 2528178 次调用。
执行时间平均:39.937424 纳秒
执行时间标准差:2.782661 纳秒
执行时间下四分位数:37.393937 纳秒(2.5%)
执行时间上四分位数:42.780432 纳秒(97.5%)
Overhead used : 1.863362 ns
警告:最终垃圾收集器(GC)需要运行时的 5.986859953402835 %
评估次数:15199992 次在 6 个样本中的 2533332 次调用。
执行时间平均:41.229082 纳秒
执行时间标准差:2.815533 纳秒
执行时间下四分位数:37.371527 纳秒(2.5%)
执行时间上四分位数:43.208673 纳秒(97.5%)
Overhead used : 1.863362 ns
警告:最终垃圾收集器(GC)需要运行时的 5.039484046472016 %
评估次数:69462 次在 6 个样本中的 11577 次调用。
执行时间平均:8.976972 微秒
执行时间标准差:587.089991 纳秒
执行时间下四分位数:8.505317 微秒(2.5%)
执行时间上四分位数:9.744296 微秒(97.5%)
Overhead used : 1.863362 ns
警告:最终垃圾收集器(GC)需要运行时的 5.773010947849351 %
评估次数:23352 次在 6 个样本中的 3892 次调用。
执行时间平均:27.277376 微秒
执行时间标准差:2.115666 微秒
执行时间下四分位数:25.719322 微秒(2.5%)
执行时间上四分位数:30.123547 微秒(97.5%)
Overhead used : 1.863362 ns


*修复*: 0001-CLJ-1843-add-to-for-faster-equality-check-against-kn.patch

7 答案

0
by

评论者:alexmiller

你看了(应用 = 3 coll)吗?只是好奇。

0

评论者:bronsa

与Util/equiv相比,Util/equivPred的优点是它可以假设提供参数的类型,避免了Util/equiv在内部确定使用哪个比较器时进行多次实例检查的运行时成本

0

评论者:alexmiller

您能否量化这几种方法在2-3个集合大小上的差异?

0
_评论者:bronsa_

以下为设置情况


(use 'criterium.core)

(defn =to [x]
  (let [pred (clojure.lang.Util/equivPred x)]
    (fn [y]
      (.equiv pred x y))))

(defn benchmark-f [f]
  (let [colls [['foo 'foo 'foo]
               [1 :foo 'foo]
               (doall (repeat 1e3 'foo))
               (doall (take 1e3 (cycle [1 :foo 'foo])))]]
    (doseq [c colls]
      (quick-bench (run! f c)))))

(benchmark-f (partial = 'foo) 的结果为



警告:最终GC消耗了1.405293826432628 %的运行时间
WARNING: Final GC required 10.202923149112559 % of runtime
Evaluation count : 3116130 in 6 samples of 519355 calls.
Execution time mean : 217.723199 ns
Execution time std-deviation : 29.425291 ns
Execution time lower quantile : 189.944710 ns ( 2.5%)
Execution time upper quantile : 261.717351 ns (97.5%)
Overhead used : 1.863362 ns
WARNING: Final GC required 4.2579397621583315 % of runtime
Evaluation count : 3138636 in 6 samples of 523106 calls.
Execution time mean : 198.985418 ns
Execution time std-deviation : 12.691848 ns
Execution time lower quantile : 182.441245 ns ( 2.5%)
Execution time upper quantile : 207.839280 ns (97.5%)
Overhead used : 1.863362 ns
WARNING: Final GC required 6.631646134523004 % of runtime
Evaluation count : 10038 in 6 samples of 1673 calls.
Execution time mean : 66.977712 µs
Execution time std-deviation : 10.411821 µs
Execution time lower quantile : 59.620690 µs ( 2.5%)
Execution time upper quantile : 84.483254 µs (97.5%)
Overhead used : 1.863362 ns

Found 1 outliers in 6 samples (16.6667 %)
low-severe  1 (16.6667 %)
Variance from outliers : 47.3059 % Variance is moderately inflated by outliers
WARNING: Final GC required 5.272721959665122 % of runtime
Evaluation count : 7908 in 6 samples of 1318 calls.
Execution time mean : 82.588512 µs
Execution time std-deviation : 5.215537 µs
Execution time lower quantile : 75.977936 µs ( 2.5%)
Execution time upper quantile : 86.849982 µs (97.5%)
Overhead used : 1.863362 ns


(benchmark-f (=to 'foo)) 的结果为


警告:最终垃圾收集器(GC)需要运行时的 7.40391654943877 %
评估次数:15169068 次在 6 个样本中的 2528178 次调用。
执行时间平均:39.937424 纳秒
执行时间标准差:2.782661 纳秒
执行时间下四分位数:37.393937 纳秒(2.5%)
执行时间上四分位数:42.780432 纳秒(97.5%)
Overhead used : 1.863362 ns
警告:最终垃圾收集器(GC)需要运行时的 5.986859953402835 %
评估次数:15199992 次在 6 个样本中的 2533332 次调用。
执行时间平均:41.229082 纳秒
执行时间标准差:2.815533 纳秒
执行时间下四分位数:37.371527 纳秒(2.5%)
执行时间上四分位数:43.208673 纳秒(97.5%)
Overhead used : 1.863362 ns
警告:最终垃圾收集器(GC)需要运行时的 5.039484046472016 %
评估次数:69462 次在 6 个样本中的 11577 次调用。
执行时间平均:8.976972 微秒
执行时间标准差:587.089991 纳秒
执行时间下四分位数:8.505317 微秒(2.5%)
执行时间上四分位数:9.744296 微秒(97.5%)
Overhead used : 1.863362 ns
警告:最终垃圾收集器(GC)需要运行时的 5.773010947849351 %
评估次数:23352 次在 6 个样本中的 3892 次调用。
执行时间平均:27.277376 微秒
执行时间标准差:2.115666 微秒
执行时间下四分位数:25.719322 微秒(2.5%)
执行时间上四分位数:30.123547 微秒(97.5%)
Overhead used : 1.863362 ns
0
_评论者:bronsa_

使用 #(= 'foo %) 而非 (partial = 'foo) 允许内联 = 并使性能略好,但 =to 仍明显胜出

WARNING: Final GC required 1.284421364203217 % of runtime
WARNING: Final GC required 10.04376144830405 % of runtime
Evaluation count : 3643032 in 6 samples of 607172 calls.
             平均执行时间:165.393131 纳秒
    执行时间标准差:1.041355 纳秒
   执行时间下四分位数:164.277060 纳秒(2.5%)
   执行时间上四分位数:166.849951 纳秒(97.5%)
                     使用的开销:1.605524 纳秒
警告:最终垃圾收集器(GC)需要运行时的 6.258680973295933 %
评估次数:3584574 次在 6 个样本中的 597429 次调用。
             平均执行时间:167.659014 纳秒
    执行时间标准差:3.821817 纳秒
   执行时间下四分位数:164.175156 纳秒(2.5%)
   执行时间上四分位数:173.210781 纳秒(97.5%)
                     使用的开销:1.605524 纳秒

Found 1 outliers in 6 samples (16.6667 %)
    低严重程度     1(16.6667 %)
 异常值的影响差异:13.8889 % 异常值导致方差中度膨胀
警告:最终垃圾收集器(GC)需要运行时的 6.914389197005716 %
评估次数:11196 次在 6 个样本中的 1866 次调用。
             平均执行时间:52.593759 微秒
    执行时间标准差:834.220092 纳秒
   执行时间下四分位数:51.510161 µs ( 2.5%)
   执行时间上四分位数:53.367649 µs (97.5%)
                     使用的开销:1.605524 纳秒
警告:最终GC消耗了6.179040224498723 %的运行时间
评估次数:在1527次调用中的6个样本,共9162次。
             平均值:66.527357 µs
    标准差:2.119652 µs
   执行时间下四分位数:65.308835 µs ( 2.5%)
   执行时间上四分位数:70.201570 µs (97.5%)
                     使用的开销:1.605524 纳秒


小型同构集合,*(partial = 'foo)*: 217ns,*#(= 'foo %)*: 165ns,*(=to 'foo)*: 39ns
小型异构集合,*(partial = 'foo)*: 192ns,*#(= 'foo %)*: 167ns,*(=to 'foo)*: 41ns
大型同构集合,*(partial = 'foo)*: 66us,*#(= 'foo %)*: 52us,*(=to 'foo)*: 8us
大型异构集合,*(partial = 'foo)*: 82us,*#(= 'foo %)*: 66us,*(=to 'foo)*: 27us
0

评论者:bronsa

显然,这是几年前就已经讨论过的内容,Rich对此表示认同https://groups.google.com/forum/#!topic/clojure-dev/0c-VNhEKVkI

0
参考: https://clojure.atlassian.net/browse/CLJ-1843 (由 bronsa 提出)
...