Testing Can';t在测试clojure数据结构时解释结果

Testing Can';t在测试clojure数据结构时解释结果,testing,data-structures,clojure,Testing,Data Structures,Clojure,一般来说,我对clojure和函数式编程相当陌生。出于对数据结构的一些基本操作(clojures默认值和一些我可能实现的操作)的速度的好奇,我写了一些东西来自动化测试操作,比如添加到结构中 我的方法对3个数据结构运行测试,根据调用方式,即使输入保持不变,也会始终返回非常不同的平均运行时间 底部带有测试和结果的代码 测试 始终以毫秒为单位 ;;;;;;;;;;;;;;;;;;EVALUATING 'run-test' directly ;;;get average speeds for addi

一般来说,我对clojure和函数式编程相当陌生。出于对数据结构的一些基本操作(clojures默认值和一些我可能实现的操作)的速度的好奇,我写了一些东西来自动化测试操作,比如添加到结构中

我的方法对3个数据结构运行测试,根据调用方式,即使输入保持不变,也会始终返回非常不同的平均运行时间

底部带有测试和结果的代码

测试
始终以毫秒为单位

;;;;;;;;;;;;;;;;;;EVALUATING 'run-test' directly
;;;get average speeds for adding 100000 random elements to list vector and set
;;;run the test 20 times and average the results
(run-test 20 conj '(() [] #{}))
;;;;;RESULT
#test.test-suite{:t-list 254/5, :t-vector 2249/20, :t-set 28641/20}  
或分别为51 112和1432表示列表向量和集合

;;;;;;;;;;;;;;;;;;EVALUATING using 'run-test-set' which calls run-test
(run-test-set   
 20              ;;;times the test is run 
 '(conj)         ;;;just run conj (adding to the ds for now)
 '((() [] #{}))   ;;;add random values to blank structures
 )  
;;;;RESULT
#test.test-series{
  :t-suites (
    #test.test-suite{
      :t-list 1297/10,
      :t-vector 1297/10,
      :t-set 1289/10}) ;;;;;;;;;;;;Result of adding values
  :t-functions (conj)}
或者对于列表向量和集合大约130,这与上面的向量的速率大致相同

有人知道为什么它会根据运行方式返回如此不同的结果吗?
这是否与clojure相关,或者可能是Java正在进行的优化?

测试clojure代码性能的正确方法是。criterium报告有关代码执行时间分布的统计信息,并确保jvm热点编译器在进行测量之前已预热。jvm热点编译器可能是您看到这些性能差异的原因

不要在
defn
内部使用
def
def
是为顶级全局定义而设计的。对于仅在一个函数中使用的绑定,请使用
let

在clojure中,定义只使用一次且仅存在用于保存几个变量的记录不是惯用方法,定义类的开销比它们可能给您带来的任何好处都要大(如果不是为了提高代码的性能,也会增加理解代码的难度)。保存记录,以便在需要专门化协议或在紧密循环中提高性能时使用

如果优先考虑的是数字的可读性,而不是准确性,则可以使用
double
强制使用可读性更强的格式进行打印

下面是如何以惯用方式测试您感兴趣的属性(来自repl会话的转录本,不过也可以从-main函数运行):

;;;;;;;;;;;;;;;;;;EVALUATING using 'run-test-set' which calls run-test
(run-test-set   
 20              ;;;times the test is run 
 '(conj)         ;;;just run conj (adding to the ds for now)
 '((() [] #{}))   ;;;add random values to blank structures
 )  
;;;;RESULT
#test.test-series{
  :t-suites (
    #test.test-suite{
      :t-list 1297/10,
      :t-vector 1297/10,
      :t-set 1289/10}) ;;;;;;;;;;;;Result of adding values
  :t-functions (conj)}
user> (require '[criterium.core :as crit])
nil
user> (def input (shuffle (range 1000000)))
#'user/input
user> (crit/bench (reduce conj [] input))
WARNING: Final GC required 3.501501258094413 % of runtime
WARNING: Final GC required 2.381979156956431 % of runtime
Evaluation count : 1680 in 60 samples of 28 calls.
             Execution time mean : 36.435413 ms
    Execution time std-deviation : 1.607847 ms
   Execution time lower quantile : 35.764207 ms ( 2.5%)
   Execution time upper quantile : 37.527755 ms (97.5%)
                   Overhead used : 2.222121 ns

Found 4 outliers in 60 samples (6.6667 %)
    low-severe   1 (1.6667 %)
    low-mild     3 (5.0000 %)
 Variance from outliers : 30.3257 % Variance is moderately inflated by outliers
nil
user> (crit/bench (reduce conj () input))
WARNING: Final GC required 9.024275674955403 % of runtime
Evaluation count : 3540 in 60 samples of 59 calls.
             Execution time mean : 19.623083 ms
    Execution time std-deviation : 3.842658 ms
   Execution time lower quantile : 17.891881 ms ( 2.5%)
   Execution time upper quantile : 26.569738 ms (97.5%)
                   Overhead used : 2.222121 ns

Found 3 outliers in 60 samples (5.0000 %)
    low-severe   3 (5.0000 %)
 Variance from outliers : 91.0960 % Variance is severely inflated by outliers
nil
user> (crit/bench (reduce conj #{} input))
WARNING: Final GC required 12.0207279064623 % of runtime
Evaluation count : 120 in 60 samples of 2 calls.
             Execution time mean : 965.389668 ms
    Execution time std-deviation : 682.645918 ms
   Execution time lower quantile : 674.958427 ms ( 2.5%)
   Execution time upper quantile : 2.287535 sec (97.5%)
                   Overhead used : 2.222121 ns

Found 9 outliers in 60 samples (15.0000 %)
    low-severe   9 (15.0000 %)
 Variance from outliers : 98.2830 % Variance is severely inflated by outliers
nil
user>