Go语言以高并发闻名于世,牛皮不能光靠吹,今天我们就来做一个对比试验,体会一下Go在并发方面的巨大优势!靶子就瞄准Java,谁让它是后端开发语言的老大哥呢。

基本任务:初始化一个100*100的矩阵,矩阵每个元素是从[0,1)随机取的双精度浮点数,计算矩阵跟自身相乘,需要100万次乘法运算。

机器配置:Linux云主机,8核16G内存。

分别尝试开10、100、1000、10000、100000、1000000个线程(协程)执行上述的基本任务。

试验结果:

测试运行时间/ms
并发度 10 100 1000 10000 100000 1000000
go 0 5 56 507 5062 50457
java 36 109 611 3063 27684 285971

速度差异很明显,go以绝对优势领先。而且随着并发度的增加,go的耗时呈线性增长;java则愈显吃力,Hold不住这么高的并发量。go可以轻松地把8个核用满,而java最多只用到5.2个核。

 

最后附上测试代码,如有问题,还请指正。

go:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package main
 
import (
    "fmt"
    "math/rand"
    "os"
    "strconv"
    "sync"
    "time"
)
 
func MatrixMultiply(A, B [100][100]float64) {
    rect := [100][100]float64{}
    for i := 0; i < 100; i++ {
        for j := 0; j < 100; j++ {
            prod := 0.0
            for k := 0; k < 100; k++ {
                prod += A[i][k] * B[k][j]
            }
            rect[i][j] = prod
        }
    }
    // fmt.Println("goroutine finish")
}
 
func main() {
    A := [100][100]float64{}
    for i := 0; i < 100; i++ {
        for j := 0; j < 100; j++ {
            A[i][j] = rand.Float64() //[0,1)上的随机数
        }
    }
 
    p, _ := strconv.Atoi(os.Args[1]) //p个并发协程
    fmt.Printf("concurrency %d\n", p)
    begin := time.Now()
    wg := sync.WaitGroup{}
    wg.Add(p)
    for i := 0; i < p; i++ {
        go func() {
            defer wg.Done()
            MatrixMultiply(A, A)
        }()
    }
    wg.Wait()
    fmt.Printf("use time %d ms\n", time.Since(begin).Milliseconds())
}

java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import java.util.Random;
 
public class MatMul extends Thread{
    private double[][] A;
    private double[][] B;
 
    MatMul(double[][] X, double[][] Y){
        A=X;
        B=Y;
    }
 
    @Override
    public void run(){
        double[][] rect=new double[100][100];
        for(int i=0;i<100;i++){
            for(int j=0;j<100;j++){
                double prod=0;
                for(int k=0;k<100;k++){
                    prod+=A[i][k]*B[k][j];
                }
                rect[i][j]=prod;
            }
        }
        // System.out.println("thread finish");
    }
 
    public static void main(String[] args) {
        Random r = new Random(1);
        double[][] A=new double[100][100];
        for(int i=0;i<100;i++){
            for(int j=0;j<100;j++){
                A[i][j]=r.nextDouble();//[0,1)上的随机数
            }
        }
        int p=Integer.parseInt(args[0]);//p个并发线程
        System.out.println("concurrency "+p);
        MatMul[] threads=new MatMul[p];
        long startTime = System.currentTimeMillis();
        for(int i=0;i<p;i++){
            MatMul thread=new MatMul(A,A);
            threads[i]=thread;
            thread.start();
        }
        for(int i=0;i<p;i++){
            try {
                threads[i].join();
            }catch(InterruptedException e) {
                System.out.println("Thread interrupted.");
            }
        }
        long endTime = System.currentTimeMillis();
        System.out.println("use time "+(endTime-startTime)+" ms");
    }
}

  

posted on   高性能golang  阅读(198)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决
点击右上角即可分享
微信分享提示