You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby中数组splat操作为何性能开销如此之大?

Ruby中Splat数组构建的性能疑问

我偏好Splat构建数组/哈希的原因

  • 它们属于数组、哈希字面量,无需追踪计算流程就能明确最终结果,语法直观清晰
  • 便于在单个表达式中构建复杂值,无需采用命令式写法(尽管可以用tap实现单赋值,但可读性差很多)

Splat的性能开销问题

实际测试发现splat操作存在明显性能开销,以下是测试代码和结果:

基础性能测试代码

require 'benchmark'

$array = (0...100).to_a

n = 100_000
Benchmark.bm do |x|
  x.report('add   ') {n.times{$array + $array + $array}}
  x.report('splat ') {n.times{[*$array, *$array, *$array]}}
end

测试结果

机器A(MRI 3.1.3)

user     system      total        real
add     0.031583   0.001421   0.033004 (  0.033006)
splat   0.050174   0.001397   0.051571 (  0.051584)

机器B(MRI 2.7.4)

user     system      total        real
add     0.278377   0.000000   0.278377 (  0.278316)
splat   0.780735   0.043730   0.824465 (  0.824377)

核心疑问

为什么基于splat的数组构建会这么慢?我原本预期splat不会比普通加法慢——毕竟AST甚至可以将两者转换,甚至应该更高效:语言能掌握所有信息,可避免加法产生的中间数组,还能预先估算最终数组大小并预留空间。

那为什么依赖方法调用(理论上更难被解释器优化)的加法方式,反而比完全暴露给解释器的splat操作更快?

补充测试:多种数组构建方式的性能对比

测试代码

require 'benchmark/ips'

ary = (0...100).to_a

Benchmark.ips do |x|
  x.report('add')          {ary + ary + ary}
  x.report('append')       {res = ary.dup; res.append(*ary); res.append(*ary); res}
  x.report('concat2')      {res = []; res.concat(ary); res.concat(ary); res.concat(ary); res}
  x.report('concat3')      {[].concat(ary, ary, ary)}
  x.report('concat_splat') {[].concat(*[ary, ary, ary])}
  x.report('flatten')      {[ary, ary, ary].flatten}
  x.report('flatten(1)')   {[ary, ary, ary].flatten(1)}
  x.report('splat')        {[*ary, *ary, *ary]}
  x.compare!
end

测试结果(机器A,MRI 3.1.3)

Warming up --------------------------------------
                 add   300.630k i/100ms
              append   140.913k i/100ms
             concat2   154.698k i/100ms
             concat3   120.459k i/100ms
        concat_splat   142.808k i/100ms
             flatten    10.329k i/100ms
          flatten(1)    52.207k i/100ms
               splat   195.946k i/100ms
Calculating -------------------------------------
                 add      3.040M (± 0.7%) i/s -     15.332M in   5.043760s
              append      1.400M (± 1.9%) i/s -      7.046M in   5.034067s
             concat2      1.532M (± 2.1%) i/s -      7.735M in   5.049821s
             concat3      1.134M (± 2.6%) i/s -      5.782M in   5.101784s
        concat_splat      1.409M (± 1.9%) i/s -      7.140M in   5.068373s
             flatten    102.948k (± 0.6%) i/s -    516.450k in   5.016786s
          flatten(1)    517.582k (± 5.2%) i/s -      2.610M in   5.058161s
               splat      1.939M (± 1.4%) i/s -      9.797M in   5.052514s

Comparison:
                 add:  3039958.8 i/s
               splat:  1939484.0 i/s -  1.57x  (± 0.00) slower
             concat2:  1532384.2 i/s -  1.98x  (± 0.00) slower
        concat_splat:  1409339.8 i/s -  2.16x  (± 0.00) slower
              append:  1400120.7 i/s -  2.17x  (± 0.00) slower
             concat3:  1134080.2 i/s -  2.68x  (± 0.00) slower
          flatten(1):   517582.1 i/s -  5.87x  (± 0.00) slower
             flatten:   102948.3 i/s - 29.53x  (± 0.00) slower

内容的提问来源于stack exchange,提问作者akim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 04:15:50