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

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

0
Clojure

函数组合函数comp(apply comp large-seq-of-fns)这样的情况下效率很低,因为其长度大于3的版本会反转序列。

如果有一个类似于comp**(或者 whatever)的替代函数会更好,这个函数就像comp一样,但它是左到右组合的。

7 个答案

0

评论者:tsdh

这里是一个实现。

0

评论者:tsdh

我的补丁有点奇怪。使用comp**创建的大型函数序列的组合要比使用comp快得多,这是预期的,因为序列不需要反转。

然而,奇怪的是,使用comp创建的序列评估速度大约比使用comp**快10-20%,尽管comp的任意参数版本是以comp**为定义的:(apply comp* (reverse (list* f1 f2 f3 fs)))

有关基准测试的详细信息,请参阅:https://groups.google.com/d/msg/clojure/MizwTxHwLE4/hGLrMfetlP8J

0
_评论者:tsdh_

这里有一些基准测试。


user> (use 'criterium.core)
nil
user> (let [coll (doall (take 1000000 (repeat inc))
       f1 (apply comp* coll)
       f2 (apply comp coll)]
       (bench (f1 0) :verbose)
       (println "---------------------------------------")
       (bench (f2 0) :verbose))
amd64 Linux 3.4.2-gentoo 2 cpu(s)
OpenJDK 64-Bit Server VM 22.0-b10
运行时参数:-agentlib:jdwp=transport=dt_socket,server=y,suspend=n -XX:+TieredCompilation -Xmx1G -Dclojure.compile.path=/home/horn/Repos/clj/testi/target/classes -Dtesti.version=0.1.0-SNAPSHOT -Dclojure.debug=false
评估计数             : 600
             平均执行时间:112.324465 ms  95.0% CI: (112.247218 ms, 112.380682 ms)
    执行时间标准差:6.513809 ms  95.0% CI: (6.477450 ms, 6.553029 ms)
         执行时间下限置信区间:105.609401 ms  95.0% CI: (105.609401 ms, 105.622918 ms)
         执行时间上限置信区间:122.353763 ms  95.0% CI: (122.353763 ms, 122.405315 ms)
---------------------------------------
amd64 Linux 3.4.2-gentoo 2 cpu(s)
OpenJDK 64-Bit Server VM 22.0-b10
运行时参数:-agentlib:jdwp=transport=dt_socket,server=y,suspend=n -XX:+TieredCompilation -Xmx1G -Dclojure.compile.path=/home/horn/Repos/clj/testi/target/classes -Dtesti.version=0.1.0-SNAPSHOT -Dclojure.debug=false
评估计数             : 1440
             平均执行时间:43.519663 ms  95.0% CI: (43.516732 ms, 43.524062 ms)
    执行时间标准差:492.299089 us  95.0% CI: (490.829889 us, 494.198137 us)
         执行时间下限置信区间:42.781398 ms  95.0% CI: (42.781398 ms, 42.781398 ms)
         执行时间上限置信区间:44.157311 ms  95.0% CI: (44.157311 ms, 44.158513 ms)
nil

0

评论者:tsdh

好的,我找到了性能差异的原因。这是因为`reverse`创建了一个`clojure.lang.PersistentList`,它的迭代速度比一个(完全实现)的LazySeq快得多。如果您以向量或列表的形式将您的fncoll提供为`(apply comp* fncoll)`,创建的复合应用将与应用程序(comp)一样快。

因此,我认为这个补丁很好,也很有意义。

0

评论者:jafingerhut

补丁0001-CLJ-1010-Add-a-left-to-right-version-of-comp-comp.patch,日期为2012年6月11日,在2014年9月5日左右对Clojure进行了一些提交后,不再干净地应用于最新的master。

我没有检查这个补丁是否容易更新。有关更新补丁的建议,请参阅《更新陈旧的补丁》部分http://dev.clojure.org/display/community/Developing Patches

0

评论者:tsdh

以下是一个更新后的补丁,它适用于截至2014年9月8日的git master。

0
参考: https://clojure.atlassian.net/browse/CLJ-1010 (由tsdh报告)
...