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

欢迎!请参见 关于 页以获取如何使用此功能的更多信息。

0
Clojure

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

如果有一个替代的 comp** (或任何其他) 函数,它就像 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
_Comment made by: 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
OpenJDK 64 位服务器 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 毫秒  95.0% CI: (112.247218 毫秒, 112.380682 毫秒)
    执行时间标准偏差: 6.513809 毫秒  95.0% CI: (6.477450 毫秒, 6.553029 毫秒)
         执行时间下限 Ci: 105.609401 毫秒  95.0% CI: (105.609401 毫秒, 105.622918 毫秒)
         执行时间上限 Ci: 122.353763 毫秒  95.0% CI: (122.353763 毫秒, 122.405315 毫秒)
---------------------------------------
amd64 Linux 3.4.2-gentoo 2 个 CPU
OpenJDK 64 位服务器 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 毫秒  95.0% CI: (43.516732 毫秒, 43.524062 毫秒)
    执行时间标准偏差: 492.299089 微秒  95.0% CI: (490.829889 微秒, 494.198137 微秒)
         执行时间下限 Ci: 42.781398 毫秒  95.0% CI: (42.781398 毫秒, 42.781398 毫秒)
         执行时间上限 Ci: 44.157311 毫秒  95.0% CI: (44.157311 毫秒, 44.158513 毫秒)
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 日,由于 Clojure 在 2014 年 9 月 5 日或附近进行了某些提交,不再干净地应用于最新的 master。

我尚未检查此补丁是否易于更新。有关更新补丁的建议,请参阅 http://dev.clojure.org/display/community/Developing Patches 中的“更新过时的补丁”部分。

0

评论者:tsdh

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

0
...