请分享您的看法,参加2024 Clojure 状态调查!

欢迎!请查看关于页面以了解更多关于这个网站如何工作的信息。

0
转换器
将一个基本重构移除 let 形式,并只需要对每个迭代进行单个计数器检查,从而提高了 25% 的性能。补丁后,最后一次迭代只需进行 2 检查(如果 counter 参数为 <= 0)...


;; master
(quick-bench (into [] (take 1000) (range 2000)))
警告:最后的 GC 需要了 34.82584189073624 % 的运行时间
评估次数:6 样本中的 2175 次 13050。
             执行时间平均值:46.921254 微秒
    执行时间标准差:1.904733 微秒
   执行时间下四分位数:45.124921 微秒(2.5%)
   执行时间上四分位数:49.427201 微秒(97.5%)
                  使用了 2.367243 纳秒开销

;; w/ patch
(quick-bench (into [] (take 1000) (range 2000)))
警告:最后的 GC 需要了 34.74448252054369 % 的运行时间
评估次数:6 样本中的 3017 次 18102。
             执行时间平均值:34.301193 微秒
    执行时间标准差:1.714105 微秒
   执行时间下四分位数:32.341349 微秒(2.5%)
   执行时间上四分位数:37.046851 微秒(97.5%)
                  使用了 2.367243 纳秒开销

6 个答案

0

评论者:toxi

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

0

评论者:alexmiller

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

0

评论者:toxi

Hi Alex,请尝试运行测试...据我所知,一切仍然按预期工作:对于(take 0)或(take -1),位置检查将失败,但我们必须确保不要为该迭代调用rf。对于所有其他(take n)情况,除了最后的迭代(会导致一个多余的neg?调用)之外,只会执行位置检查。当前的路径/实现总是会对所有迭代执行2次检查,因此速度较慢。

0

评论者:alexmiller

只有在take传递给n <= 0时,neg?情况才会被触发,因此我认为这是正确的。然而,您可能考虑以某种不同的方式处理该特殊情况 - 例如,可以将其从transducer函数中完全拉出来,并作为一个独立的transducer函数创建。我不确定是否值得这样做,但这只是一个想法。

0
评论人:toxi_

好主意,Alex!这个第二个补丁移除了{{neg?}}检查,并为n <= 0的情况添加了一个快速退出transducer。这也使它更快一些


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


(现在比原始版本快35%)
0
...