声明
本篇测试并非基准测试,相关测试结果仅供参考,如有错误之处还望指出。
环境
JDK版本
openjdk version “19” 2022-09-20
Golang版本
go version go1.19.1
Rust版本
rustc 1.64.0 (a55dd71d5 2022-09-19)
机器
centos7.9.2/16G内存/4核CPU
测试工具
wrk
测试
为了更接近语言的原生性能我们没有使用相关框架进行操作,采用最原始的写法,主要从内存占用、编译速度、并发量、计算速度等几个方面来分析
注意点:
- 针对与rust我们需要通过开启其优化才能有性能提升
--release
,普通开发模式下可能比较慢
业务场景:计算密集
执行一百次递归调用计算斐波拉契数时间空间对比
业务场景:多线程
通过最新的虚拟线程和协程(Rust中没有虚拟线程,直接使用线程)计算斐波拉契数时间空间对比
业务场景:高并发
使用各种编写的http服务进行压测,通过使用wrk开启8线程500连接进行请求,其数据结构如下
1 2 3
| wrk -c500 -t8 -d30s --latency http://147.106.210.183:8000/serial/abcdefghijklmnopqrist wrk -c500 -t8 -d30s --latency http://147.106.210.183:8001/serial/abcdefghijklmnopqrist wrk -c500 -t8 -d30s --latency http://147.106.210.183:8001/serial/abcdefghijklmnopqrist
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| Running 30s test @ http://147.106.210.183:8000/serial/abcdefghijklmnopqrist 8 threads and 500 connections Thread Stats Avg Stdev Max +/- Stdev Latency 11.34ms 21.70ms 436.09ms 98.97% Req/Sec 4.08k 794.69 6.63k 84.37% Latency Distribution 50% 9.46ms 75% 12.30ms 90% 14.94ms 99% 38.12ms 961548 requests in 30.02s, 104.54MB read Socket errors: connect 0, read 23020, write 48, timeout 0 Requests/sec: 32030.69 Transfer/sec: 3.48MB
cpu 570% men 394M jar siez 17M
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| Running 30s test @ http://147.106.210.183:8001/serial/abcdefghijklmnopqrist 8 threads and 500 connections Thread Stats Avg Stdev Max +/- Stdev Latency 13.33ms 9.67ms 106.38ms 62.59% Req/Sec 3.62k 3.28k 49.52k 91.97% Latency Distribution 50% 13.46ms 75% 19.77ms 90% 25.06ms 99% 39.45ms 856099 requests in 30.09s, 124.10MB read Socket errors: connect 0, read 670, write 0, timeout 0 Requests/sec: 28448.40 Transfer/sec: 4.12MB
cpu 422.7% men 42M file size 1k
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| wrk -c500 -t8 -d30s --latency http://localhost:8002 Running 30s test @ http://localhost:8002 8 threads and 500 connections Thread Stats Avg Stdev Max +/- Stdev Latency 8.29ms 7.45ms 133.77ms 85.81% Req/Sec 5.59k 3.31k 34.53k 79.66% Latency Distribution 50% 6.35ms 75% 10.89ms 90% 17.23ms 99% 33.15ms 1330208 requests in 30.09s, 164.92MB read Socket errors: connect 0, read 685, write 0, timeout 0 Requests/sec: 44202.84 Transfer/sec: 5.48MB
cpu 330% men 19M file size 3M
|
总结
java:网站后端、微服务应用、工程级别的应用,生态活跃且完整,其弊端是占用资源多,和另外两种相比显得十分臃肿。Java屏蔽了底层的复杂、容易出错的地方(如指针,内存管理等),毋庸置疑生态是三者中最好的,有很多成熟的方案,如果需要快速搭建功能抢占市场用户资源是个不错的选择
golang:源于谷歌开源,在kubernetes的加持下受到了广大开发者的喜爱,其编程风格简洁,性能强悍同时也是带有GC的编程语言,是目前高并发、云原生开发的不二之选。
rust:适合系统级应用、追求极致性能。rust是最新出的编程语言,其站在其他语言的肩膀上规避了许多问题,它本身是一门系统的编程语言其有自己独特的一套对象生命周期和作用范围管理机制,在编译时就对代码进行检查,强制我们规避可能出现的问题,注重内存安全、避免类似于C/C++发生内存泄露、野指针的问题,但有能达到C/C++的性能。
在现在的环境下微服务开发在容器化的支持下已经可以实现多语言混合开发,需要结合自身实际业务来对其进行选型,不同的场景选用不同的技术带来的收益也会有所差别。
资料
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Solution{ public static long fibonacci(long n) { if (n == 1 || n == 0) return 1; return fibonacci(n - 1) + fibonacci(n - 2); } public static void m2() throws InterruptedException { int cnt = 100; long max = 40; new Scanner(System.in).next(); List<Callable<Long>> tasks = new ArrayList<>(); for (int i = 0; i < cnt; i++) tasks.add(() -> fibonacci(max)); long start = System.currentTimeMillis(); Executors.newVirtualThreadPerTaskExecutor().invokeAll(tasks); long time = System.currentTimeMillis() - start; System.out.println(String.format("总耗时:%d 毫秒", time)); } }
|
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
| func fibonacci(n uint64) uint64 { if n == 0 || n == 1 { return 1 } return fibonacci(n-1) + fibonacci(n-2) }
func main() { fmt.Scanln() fmt.Println("start...") cnt := 100 max := 40 t := make([]time.Duration,cnt) for i := 0; i < cnt; i++ { start := time.Now() fibonacci(uint64(max)) t[i] = time.Since(start) } time := time.Duration(0) for _, v := range t { time+=v } total:=time.Milliseconds() fmt.Printf("总耗时:%v 毫秒,平均耗时:%v 毫秒", total, total / int64(cnt)) }
func main1() { fmt.Scanln() fmt.Println("start...") cnt := 100 max := uint64(40) start := time.Now() group:=sync.WaitGroup{} for i := 0; i < cnt; i++ { group.Add(1) go func() { defer func() { group.Done() }() fibonacci(max) }() } group.Wait() t := time.Since(start) total:=t.Milliseconds() fmt.Printf("总耗时:%v 毫秒", total) }
|
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
| fn fibonacci(n:i64)->i64{ if n==1||n==0 { return 1; } return fibonacci(n-1) + fibonacci(n-2); }
pub fn main() { let mut buf = [0]; io::stdin().read(&mut buf).unwrap(); println!("start..."); let cnt :u128 = 100; let mut time:Vec<u128> = Vec::with_capacity(cnt as usize); let max = 40; for _ in 0..cnt { let now = Instant::now(); fibonacci(max); time.push(now.elapsed().as_millis()); } let mut total = 0; for t in time { total+=t; } println!("总耗时:{} 毫秒,平均耗时:{} 毫秒",total,total/cnt); }
pub fn main() { let mut buf = [0]; io::stdin().read(&mut buf).unwrap(); println!("start..."); let cnt :u128 = 100; let max :i64 = 40; let now = Instant::now(); let mut handles = Vec::with_capacity(cnt as usize); for _ in 0..cnt { handles.push(thread::spawn(move|| { fibonacci(max); })); } for handle in handles { handle.join().unwrap(); } let spend = now.elapsed().as_millis(); println!("总耗时:{} 毫秒",spend); }
|