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

欢迎!有关如何使用本网页的更多信息,请参阅 关于 页面。

0
转换器
基本重构,移除了 let 形式,并对每个迭代只需要进行一次计数器检查,提高了 25% 的性能。在补丁中,最后一次迭代只需要进行 2 次检查(假设计数器参数小于等于 0)...


;; master
(quick-bench (into [] (take 1000) (range 2000)))
WARNING: 最终 GC 需要 34.82584189073624 % 的运行时间
评估数计算:6 个样本中 2175 次调用共 13050 次。
             执行时间平均值: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)))
WARNING: 最终 GC 需要 34.74448252054369 % 的运行时间
评估数计算:6 个样本中 3017 次调用共 18102 次。
             执行时间平均值: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

评论由:toxi 提供

嗨Alex,尝试运行测试...在我看来,一切仍在按预期运行:对于(take 0)或(take -1),pos?检查失败,但我们必须确保不调用该迭代的rf。对于所有其他(take n)案例,除了最后一次迭代(导致一个多余的neg?调用外),只执行pos?检查。当前的路径/实现对所有迭代总是进行2次检查,因此(慢得多)。

0

评论由:alexmiller 提供

neg?案例仅会在传递n <= 0时被击中,因此我认为这是正确的。然而,您可以考虑以不同方式处理这种情况——例如,可以将其完全从transducer函数中提取出来,并作为一个独立的transducer函数创建。我不确定这是否值得做,但这是一个想法。

0
评论者:toxi

好主意,Alex!这个第二个补丁删除了{{neg?}}检查,并为n <= 0的情况添加了一个快速退出transducer。这还使其稍微快一点。


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


(现在比原始版本快约35%)
0
欢迎使用Clojure Q&A,您可以在其中向Clojure社区的成员提问题和获取答案。
...