OutOfMemoryError:GC开销限制超出了Criterium

时间:2017-08-20 21:48:10

标签: clojure out-of-memory benchmarking

我正在尝试使用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)不足以使数据适合并且垃圾收集器尝试释放空间但是无法执行此操作。但是,如下所示对表达式进行微基准测试不会产生此错误

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

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

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

修改:开始新的代理时,请使用以下代码

{: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}

1 个答案:

答案 0 :(得分:2)

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

;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(范围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)))