场景:启动四个线程或协程,每个任务单独累加50000000000次。
机器配置:intel i5-3470 3.2GHZ 8G win7 64 pro
代码如下
go:
package com.paxos.thread;
public class TestThreadMultihttp {
Runnable r = new Runnable() {
@Override
public void run() {
long i = 0;
while (i < 50000000000l) {
i++;
}
}
};
public static void main(String[] args) throws InterruptedException {
Long a = System.currentTimeMillis();
String[] users = new String[]{"a", "b", "c", "d"};
for (String str : users) {
TestThreadMultihttp t = new TestThreadMultihttp();
Thread t1 = new Thread(t.r);
t1.start();
t1.join();
}
System.out.println(System.currentTimeMillis()-a);
}
}
java:
package main
import (
"sync"
"time"
"fmt"
"runtime"
)
var wg sync.WaitGroup
var users = []string{"a", "b", "c", "d"}
func main() {
runtime.GOMAXPROCS(4)
fmt.Printf("Time begin %s \n", time.Now())
wg.Add(len(users))
for _, name := range users {
go do(name)
}
wg.Wait()
fmt.Printf("Time end %s \n", time.Now())
}
func do(name string) {
defer wg.Done()
var i = 0
for {
if i < 50000000000 {
i++
} else {
return
}
}
}
运行时间:
GO:16.7(s)
JAVA:59.7(s)
原因分析:
java多线程运行中,没有把线程与cpu绑定,存在上下文切换(switch context)等,影响效率。
CPU Cache切换【1】:
CPU Cache分成了三个级别: L1, L2, L3. 级别越小越接近CPU, 所以速度也更快, 同时也代表着容量越小. L1是最接近CPU的, 它容量最小, 例如32K, 速度最快,每个核上都有一个L1 Cache(准确地说每个核上有两个L1 Cache,
一个存数据 L1d Cache, 一个存指令 L1i Cache). L2 Cache 更大一些,例如256K, 速度要慢一些, 一般情况下每个核上都有一个独立的L2 Cache; L3 Cache是三级缓存中最大的一级,例如12MB,同时也是最慢的一级, 在同一个CPU插槽之间的核共享一个L3 Cache.
从CPU到 大约需要的CPU周期 大约需要的时间(单位ns)
寄存器 1 cycle
L1 Cache ~3-4 cycles ~0.5-1 ns
L2 Cache ~10-20 cycles ~3-7 ns
L3 Cache ~40-45 cycles ~15 ns
跨槽传输 ~20 ns
内存 ~120-240 cycles ~60-120ns
go语言充分发挥了多核并行的优势,每个CPU都接近100%负荷运行,效率大大提高。
参考:
【1】http://coderplay.iteye.com/blog/1485760