OutOfMemoryError: GC overhead limit exceeded Criterium

OutOfMemoryError: GC overhead limit exceeded Criterium

我正在尝试使用 Criterium 库对表达式进行基准测试。表达式是

(vec (range 10000000))

为了对它进行基准测试,我输入了

 (criterium.core/bench (vec (range 10000000)))

过了一会儿我得到

 OutOfMemoryError GC overhead limit exceeded  java.lang.Long.valueOf (Long.java:840)

正如我所见here 这意味着堆的最大大小 (1 GB) 不足以容纳数据,垃圾收集器试图释放 space 但无法释放这样做。但是,对如下表达式进行微基准测试不会产生此错误

(dotimes [i 60] (time (vec (range 10000000))))

顺便说一下,我将它设置为 60 次,因为我看到 here bench 宏默认执行 60 次。

问题是为什么在使用 Criterium 时会发生这种情况。

编辑: 当开始一个新的 repl 下面的代码时

{:max (.maxMemory (Runtime/getRuntime)), :total (.totalMemory (Runtime/getRuntime))}

产出

{:max 922746880, :total 212860928}

在我运行(dotimes [i 60] (time (vec (range 10000000))))(criterium.core/bench (vec (range 10000000)))

之后

它输出

{:max 922746880, :total 922746880}

我能够通过使用此测试重现该行为:

;project.clj
:profiles {:test    {:jvm-opts ["-Xms1024m" "-Xmx1024m"]}}

(:require [clojure.test :refer :all]
          [criterium.core :as ben])

(deftest ^:focused ben-test
  (is (ben/with-progress-reporting
        (ben/bench (vec (range 10000000))))))

堆栈跟踪如下所示:

Estimating sampling overhead                                         
Warming up for JIT optimisations 10000000000 ...                     
compilation occurred before 377618 iterations                      
...

Estimating execution count ...
Sampling ...
Final GC...
Checking GC...
Finding outliers ...
Bootstrapping ...
Checking outlier significance
Warming up for JIT optimisations 10000000000 ...
compilation occurred before 1 iterations

criterium.core$execute_expr_core_timed_part$fn__40395.invoke (core.clj:370)                                                                                                                                                                                                        
criterium.core$execute_expr_core_timed_part.invokeStatic (core.clj:366)                                                                                                                                                                                                            
criterium.core$execute_expr_core_timed_part.invoke (core.clj:345)                                                                                                                                                                                                                  
criterium.core$execute_expr.invokeStatic (core.clj:378)                                                                                                                                                                                                                            
criterium.core$execute_expr.invoke (core.clj:374)                                                                                                                                                                                                                                  
criterium.core$warmup_for_jit.invokeStatic (core.clj:428)                                                                                                                                                                                                                          
criterium.core$warmup_for_jit.invoke (core.clj:396)                                                                                                                                                                                                                                
criterium.core$run_benchmark.invokeStatic (core.clj:479)                                                                                                                                                                                                                           
criterium.core$run_benchmark.invoke (core.clj:470)                                                                                                                                                                                                                                 
criterium.core$benchmark_STAR_.invokeStatic (core.clj:826)                                                                                                                                                                                                                         
criterium.core$benchmark_STAR_.invoke (core.clj:812) 

这里可以看到错误发生在JIT-Warning-Up这一步。有趣的一点是函数 execute-expr-core-timed-part (core.clj:345)。此函数执行表达式 (vec (range 10000000)) n 次并每次将返回值保存到所谓的可变位置。我的假设是我们这里有内存泄漏。

(time-body
  (loop [i (long (dec n))
      v (f)]
==> (set-place mutable-place v**)
    (if (pos? i)
     (recur (unchecked-dec i) (f))
     v)))