2024年Clojure调查问卷中分享你的想法!

欢迎!请查阅关于页面以了解此功能的相关信息。

0
Transducers
删除let形式的基本重构,每个迭代只需要进行单个计数检查,从而提高25%的性能。使用补丁,最后一次迭代只需要2次检查(假设计数器参数小于等于0)...


;; master
(quick-bench (into [] (take 1000) (range 2000)))
警告:最后的垃圾回收占用了运行时间的34.82584189073624 %。
评估次数:13050,在6个样本中的2175次调用。
             平均执行时间:46.921254 µs
    执行时间标准差:1.904733 µs
   执行时间下四分位数:45.124921 µs (2.5%)
   执行时间上四分位数:49.427201 µs (97.5%)
                   用于开销:2.367243 ns

;; w/ patch
(quick-bench (into [] (take 1000) (range 2000)))
警告:最后的垃圾回收占用了运行时间的34.74448252054369 %。
评估次数:18102,在6个样本中的3017次调用。
             平均执行时间:34.301193 µs
    执行时间标准差:1.714105 µs
   执行时间下四分位数:32.341349 µs (2.5%)
   执行时间上四分位数:37.046851 µs (97.5%)
                   用于开销:2.367243 ns

6 答案

0

评论者:toxi

提出的补丁,通过所有现有测试

0

评论者:alexmiller

从表面的浏览中,我看到pos?和neg?的检查,这两者都排除了0,这让我对此分支有所怀疑。实际上这可能没问题,但我需要更仔细地阅读它。

0
by

评论者:toxi

嗨,Alex,试试运行测试...据我所知,一切仍然按预期工作:对于(take 0)或(take -1),pos?检查失败,但我们必须确保不要调用rf的该迭代。在其他所有(take n)的情况下,只执行pos?检查,除了最后一次迭代(它会导致一个额外的neg?调用)。当前的路径/实现对所有迭代常规做两次检查,因此(得多慢)。

0
by

评论者:alexmiller

只有当take传入n <= 0时,才会触发neg?案例,所以我认为这是正确的。然而,你可能需要考虑以不同的方式处理该特定案例 - 例如,它可能从整个transducer函数中抽出,作为完全独立的单独transducer函数创建。我不确定这值得做,但这是一个想法。

0
by
评论人:toxi_

好主意,Alex!这个第2个补丁删除了{{neg?}}检查,并为n <= 0的情况添加了一个快速跳转transducer。这也有助于使它更快一点


(quick-bench (into [] (take 1000) (range 2000)))
评估次数:在6个样本的3395次调用中,共20370次。
             执行时间平均值:30.302673 µs


(现在比原始快约35%)
0
by
...