如何在Clojure中对函数进行基准测试?

42

我知道可以使用time函数/宏将评估函数所需的时间打印在屏幕或标准输出上。

time宏返回所评估函数的值,这使它很适合用于内联。然而,我想在特定情况下自动测量运行时间。

是否有一个库中的函数可以返回经过的时间以帮助进行基准测试?


可能是为Clojure设计的性能分析工具?的重复问题。 - Gordon Gustafson
我不这么认为,所涉及的问题是关于外部基准测试的,而这个问题更多地涉及到代码工具化。我必须承认,有人在寻找五年前的问题中寻找重复内容,这让我感到惊讶。 - Peter Tillemans
3个回答

32
如果只是想通过程序捕获字符串,你可以在使用 time 之前将 *out* 绑定到其他内容。
user=> (def x (with-out-str (time (+ 2 2))))
#'user/x
user=> x
"\"Elapsed time: 0.119 msecs\"\n"

如果您想更加控制日期时间的格式,那么您可以使用Java的系统时间方法来创建自己的time版本,这正是time宏在后台使用的方法:

user => (macroexpand '(time (+ 2 2)))
(let* [start__4197__auto__ (. java.lang.System (clojure.core/nanoTime))  
       ret__4198__auto__ (+ 2 2)] 
     (clojure.core/prn (clojure.core/str "Elapsed time: " (clojure.core//     
          (clojure.core/double 
               (clojure.core/- (. java.lang.System (clojure.core/nanoTime)) 
                                start__4197__auto__)) 1000000.0) " msecs"))
 ret__4198__auto__)

使用那个基本结构,用你喜欢的任何报告机制替换对prn的调用。


1
谢谢,我也考虑从这个开始。Criterium库确实非常适合。但是,除非你知道Haskell库,否则你不会在使用Google时偶然发现它。 - Peter Tillemans
1
@PeterTillemans 好的,既然在StackOverflow中提到了,那么现在我们就知道了。 :-) - Tim Clemons

28

您可能想了解Hugo Duncan的Clojure基准测试库Criterium

从README中得知:

Criterium可测量表达式的计算时间。它旨在解决一些基准测试陷阱,特别是在JVM上的基准测试。

这包括:

  • 多次评估的统计处理
  • 包含一个预热期,旨在允许JIT编译器优化其代码
  • 在测试之前清除GC,以将定时与测试之前的GC状态隔离
  • 测试后强制进行GC以估计清理对定时结果的影响

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接