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) 的情况,只有 pos? 检查在最后一个迭代之外执行(这导致一个额外的 superfluous neg? 调用)。当前的路径 实现 总是对所有迭代进行 2 次检查,因此 (得多)慢。

0

评论由:alexmiller 提出

只有当传递给 take 的 n ≤ 0 时,才会触发 neg? 的情况,所以我认为这是正确的。然而,你可能会考虑以不同的方式处理这种情况 - 例如,它可以从 transducer 函数中完全提取出来,并作为一个独立的 transducer 函数创建。我不确定这是否值得做,但这是一个想法。

0
评论者:toxi_

好主意,Alex!这个第2个补丁移除了 {{neg?}} 检查,并为 n ≤ 0 的情况添加了一个快速退出 transducer。这也让它稍微快一点


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


(现在大约比原始版本快 35%)
0
参考:https://clojure.atlassian.net/browse/CLJ-1804(由 toxi 报告)
...