Clojure的:为什么皮亚杰这么慢? [英] Clojure: why is aget so slow?

查看:90
本文介绍了Clojure的:为什么皮亚杰这么慢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的思想,Clojure的载体相比,Java数组有轻微的性能损失。因此,我认为传统智慧是为你的code的那些性能关键部分,你会更好使用Java数组。

In my thinking, clojure vectors have a slight performance hit compared to java arrays. As a result I thought that "conventional wisdom" was that for those performance-critical parts of your code, you'd be better off using java arrays.

我的测试,但认为这是不正确的:

My tests however suggest that this is not true:

Clojure 1.3.0
user=> (def x (vec (range 100000)))
#'user/x
user=> (def xa (int-array x))
#'user/xa
user=> (time  (loop [i 0 s 0] (if (< i 100000) (recur (inc i) (+ s (nth x i))) s)))
"Elapsed time: 16.551 msecs"
4999950000
user=> (time  (loop [i 0 s 0] (if (< i 100000) (recur (inc i) (+ s (aget xa i))) s)))
"Elapsed time: 1271.804 msecs"
4999950000

正如你所看到的,皮亚杰增加了约800%的时间这个加法。这两种方法仍比原生的Java方法要慢,但:

As you can see, the aget adds about 800% time to this addition. Both methods still are way slower than native java though:

public class Test {                                                                                                                                                                                                                                                                                                           
    public static void main (String[] args) {                                                                                                                                                                                                                                                                                 
        int[] x = new int[100000];                                                                                                                                                                                                                                                                                            
        for (int i=0;i<100000;i++) {                                                                                                                                                                                                                                                                                          
            x[i]=i;                                                                                                                                                                                                                                                                                                           
        }                                                                                                                                                                                                                                                                                                                     
        long s=0;                                                                                                                                                                                                                                                                                                             
        long end, start = System.nanoTime();                                                                                                                                                                                                                                                                                  
        for (int i=0;i<100000;i++) {                                                                                                                                                                                                                                                                                          
            s+= x[i];                                                                                                                                                                                                                                                                                                         
        }                                                                                                                                                                                                                                                                                                                     
        end = System.nanoTime();                                                                                                                                                                                                                                                                                              
        System.out.println((end-start)/1000000.0+" ms");                                                                                                                                                                                                                                                                      
        System.out.println(s);                                                                                                                                                                                                                                                                                                
    }                                                                                                                                                                                                                                                                                                                         
}                              

> java Test
1.884 ms
4999950000

所以,应我的结论是,皮亚杰比第n个慢80倍,慢约800倍[] -access在java中?

So, should my conclusion be that aget is 80 times slower than nth, and about 800 times slower than []-access in java?

推荐答案

我怀疑这是下降到了皮亚杰功能反射和原始类型的自动装箱......

I suspect this is down to reflection and autoboxing of the primitive types by the aget function....

幸运的是皮亚杰/ ASET必须为避免反射,只是做了直接序列基本数组高性能重载[I]访问(见的这里和<一个href=\"https://github.com/clojure/clojure/blob/clojure-1.3.0/src/jvm/clojure/lang/RT.java#L2067\">here).

Luckily aget/aset have performant overloads for primitive arrays that avoid the reflection and just do a direct array[i] access (See here and here).

您只需要通过一种暗示拿起右边的功能。

You just need to pass a type hint to pick up the right function.

(type xa)
[I    ; indicates array of primitive ints

; with type hint on array
;
(time (loop [i 0 s 0] 
        (if (< i 100000) (recur (inc i) 
          (+ s (aget ^ints xa i))) s))) 
"Elapsed time: 6.79 msecs"
4999950000

; without type hinting
;
(time (loop [i 0 s 0] 
        (if (< i 100000) (recur (inc i) 
          (+ s (aget xa i))) s)))
"Elapsed time: 1135.097 msecs"
4999950000

这篇关于Clojure的:为什么皮亚杰这么慢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆