任何时候都不能人云亦云,别人说好的东西必须亲自尝试过之后才会有真切的体会。
对于erlang也是如此,因为自己之前一直是用java开发的,所以自觉不自觉得喜欢用java 和erlang来作比较,不比较还好,一比较之后真的会使自己陷入对erlang的怀疑。
测试1:
erlang执行速度和java比较:
测试内容是,创建1000万个有5个字符的随机字符串。
非常抱歉的高速各位,我测试的结果是erlang慢很多,我真希望是我代码写的有问题。
测试用的服务器是 16核24G内存的服务器,公平起见,都没有使用并发多进程,多线程。
Java代码如下:
public class TestDict {
public static void main(String[] args) {
final long current = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
createRandomWord();
}
System.out.println("consume:" + (System.currentTimeMillis() - current));
}
private static String createRandomWord() {
char[] chars = new char[5];
for (int i = 0; i < chars.length; i++) {
chars[i] = (char) (97 + (int) (Math.random() * 26));
}
return new String(chars);
}
}
编译:
javac TestDict.java
执行:
java TestDict
执行结果:
consume:1868
Erlang代码:
-module(test_dict). -compile(export_all). just_create_words(0)-> ok; just_create_words(N)-> create_random_word(), just_create_words(N-1). create_random_word()-> create_random_word([],0). create_random_word(Acl,5)-> Acl; create_random_word(Acl,N)-> create_random_word([97+ trunc(random:uniform()*26) |Acl],N+1).
编译:
erlc test_dict.erl
执行:
timer:tc(test_dict,just_create_words,[10000000]).
执行结果:
{29546820,ok} 29.5秒
结果对比:
看见了吧 java执行只需要1.8秒,而erlang需要29.5秒,如果说相差个1秒那还说得过去,为啥相差这么多?难道我写的代码有问题?
测试2:
测试二是在上测试1的基础上,将创建出的随机字符串put到map对象中他,map对象的value是一个Integer值,当map对象中如果已经有一个相同的key的话就将对应key的value值加一。
还是创将1000万个5个字符串的随机字符串,分别统计执行时间。
以下是java代码:
public class TestDict {
public static void main(String[] args) {
Map<String, AtomicInteger> wordCount = new HashMap<String, AtomicInteger>();
final long current = System.currentTimeMillis();
String key = null;
AtomicInteger value = null;
for (int i = 0; i < 10000000; i++) {
key = createRandomWord();
value = wordCount.get(key);
if (value == null) {
wordCount.put(key, new AtomicInteger(1));
} else {
wordCount.get(key).incrementAndGet();
}
}
System.out.println("consume:" + (System.currentTimeMillis() - current));
System.out.println("key size:" + wordCount.size());
}
private static String createRandomWord() {
char[] chars = new char[5];
for (int i = 0; i < chars.length; i++) {
chars[i] = (char) (97 + (int) (Math.random() * 26));
}
return new String(chars);
}
}
编译:
javac TestDict.java
执行:
java TestDict
执行结果:
consume:13698 key size:6759849
Erlang代码:
-module(test_dict).
-compile(export_all).
test_create_word(Dict,0)->
ok;
test_create_word(Dict,N)->
dict:update_counter(create_random_word(),1,Dict),
test_create_word(Dict,N-1).
create_random_word()->
create_random_word([],0).
create_random_word(Acl,5)->
Acl;
create_random_word(Acl,N)->
create_random_word([97+ trunc(random:uniform()*26) |Acl],N+1).
编译:
erlc test_dict.erl
执行:
timer:tc(test_dict , test_create_word , [dict:new(),10000000]).
执行结果:
{38897271,ok} 38,8秒
结果对比:
对比两次执行操作时间,需要减去测试一的执行时间,多出来的时间就是操作K->V对象的时间:
Java版本执行时间:13.6-1.8=11.8秒
erlang版本执行时间:38.8-29.5=9.3秒
从测试结果来看,erlang的dict 对象执行速度还是比java的map对象快的,还快了两秒多。之前我有一个担心,那就是erlang的immutable object,我总是在想erlang是如何操作dict数据结构的呢,因为每次更新dict中的一个k-value值都会创建一个新的dict对象(这个操作对象的方式,在java中是完全不可以接受的),那么随着dict中key越来越多,操作dict数据结构的时间也会越来越长的,但是经过测试2的结果,让我完全打消对erlang dict性能的怀疑。
总结:
通过两个测试结果综合来看,erlang在计算随机数环节慢了,估计是random:uniform()执行比较慢的原因,另外欣慰的是在测试2中对k-v操作中erlang的dict胜出了,今后我可以在erlang的代码中放心地使用dict了。