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

如何获取Ruby Proc/Lambda源码?优化Benchmark.ips显示内容

问题:Benchmark.ips自定义参数时无法显示期望的方法名

尝试执行的代码

Benchmark.ips(-> { add }, -> { sub })

当前实现

def Benchmark.ips(*reports, &block)
  if reports.any?
    super() do |x|
      reports.each do |report|
        x.report(report.to_s) { report.call }
      end
    end
  else
    super
  end
end

出现的问题

当前输出会显示Proc对象的默认字符串表示,而不是期望的add和sub:

#<Proc:0x0000000102d0d3f8 a.rb:61 (lambda)>
                         1.810M i/100ms

需求

希望在x.report的名称位置显示对应的方法名add和sub,替代当前的Proc对象字符串。


解决方案

Ruby的Proc/lambda本身不会记录关联的方法名称,所以需要调整参数传递方式或通过解析代码来实现需求:

方案1:传递名称与Proc的哈希(推荐)

这种方式最可靠,直接明确指定每个基准测试的名称:

# 修改调用代码
Benchmark.ips(add: -> { add }, sub: -> { sub })

# 修改实现代码
def Benchmark.ips(reports = {}, &block)
  if reports.is_a?(Hash) && !reports.empty?
    super() do |x|
      reports.each do |name, report|
        x.report(name.to_s) { report.call }
      end
    end
  else
    super
  end
end

方案2:解析Lambda源代码(仅适用于简单场景)

如果必须保留原调用方式,可以尝试读取Lambda的源代码来提取方法名,但这种方式依赖固定的代码格式:

def Benchmark.ips(*reports, &block)
  if reports.any?
    super() do |x|
      reports.each do |report|
        file, line = report.source_location
        next unless file && line
        
        # 读取对应行的代码并提取方法名
        code_line = File.readlines(file)[line - 1].strip
        method_name = if code_line =~ /->\s*\{\s*(\w+)\s*\}/
                       $1
                     else
                       report.to_s
                     end
        
        x.report(method_name) { report.call }
      end
    end
  else
    super
  end
end

注意:如果Lambda内部有复杂逻辑(比如多行代码、参数传递),这个解析逻辑会失效,仅适合-> { method }这种简单格式。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 05:08:22