net8正式版出来两个月,现在性能到底如何呢,做个简单的例子和其他语言比较一下,测试内容是查找1000000以内的质数,代码不多,但包含了循环计算和Math库函数调用,直观的看一下语言之间差距是多少,心里有个底,测试机是笔记本surface book 2 intel i7 有个四五年了,不过还能跑
单线程篇
首先来看看google的王牌语言golang,语法简单但性能号称不输C++,先看一下go 1.20.2
package mainimport ("fmt""math""time"
)func isPrime(num int) bool {if num <= 1 {return false}for i := 2; i <= int(math.Sqrt(float64(num))); i++ {if num%i == 0 {return false}}return true
}func countPrimes(n int) int {count := 0for i := 2; i < n; i++ {if isPrime(i) {count++}}return count
}func main() {num := 1000000startTime := time.Now()result := countPrimes(num)endTime := time.Now()fmt.Printf("The number of prime numbers less than %d is: %d\n", num, result)fmt.Printf("Execution time: %v\n", endTime.Sub(startTime))
}
编译之后看看耗时是多少
然后看看net6
using System;
using System.Diagnostics;namespace FindPrimeNet6
{class Program{static bool IsPrime(int num){if (num <= 1){return false;}for (int i = 2; i <= Math.Sqrt(num); i++){if (num % i == 0){return false;}}return true;}static int CountPrimes(int n){int count = 0;for (int i = 2; i < n; i++){if (IsPrime(i)){count++;}}return count;}static void Main(string[] args){int num = 1000000;Stopwatch timer = Stopwatch.StartNew();int result = CountPrimes(num);timer.Stop();Console.WriteLine($"The number of prime numbers less than {num} is: {result}");Console.WriteLine($"Execution time: {timer.ElapsedMilliseconds:F4} ms");}}
}
运行一下看看
然后重头来了net8 开启aot怎么样呢
看来速度没提升,应该是启动速度提高了
然后我们再看看大家心目中最慢的python,装了3.11.7版本
#import numba
import math
import time#@numba.jit
def is_prime(num):if num <= 1:return Falsefor i in range(2, int(math.sqrt(num)) + 1):if num % i == 0:return Falsereturn True#@numba.jit
def count_primes(n):count = 0for i in range(2, n):if is_prime(i):count += 1return countnum = 1000000
start_time = time.perf_counter()
result = count_primes(num)
end_time = time.perf_counter()time_elapsed = end_time - start_timeprint(f"The number of prime numbers less than {num} is: {result}")
print(f"Execution time: {time_elapsed*1000:.4f}ms")
看看普通模式跑跑要多少毫秒
竟然3秒7 是golang10倍,然后让我们开了jit再跑一次
看起来 并没有差前两个语言很多
然后打包exe再执行一次 差强人意哈哈 单线程性能就这样了,参考一下 。
并行计算篇
测试完上面的,各个语言粉丝说不服,根本没有发挥出优势,结果并不能说明真正的快慢,那我又重新写了一下这三个语言的并行计算方法,比较这种情况到底谁快,结果可能你想不到。
首先还是golang 这次采用routine协程方式计算代码贴上
package mainimport ("fmt""sync""time"
)func isPrime(num int) bool {if num <= 1 {return false}for i := 2; i*i <= num; i++ {if num%i == 0 {return false}}return true
}func countPrimes(start, end int, resultChan chan int, wg *sync.WaitGroup) {defer wg.Done()count := 0for i := start; i < end; i++ {if isPrime(i) {count++}}resultChan <- count
}func main() {startTime := time.Now()num := 1000000goroutines := 10results := make(chan int, goroutines)var wg sync.WaitGroupwg.Add(goroutines)step := num / goroutinesfor i := 0; i < goroutines; i++ {start := i * stepend := (i + 1) * stepif i == goroutines-1 {end = num}go countPrimes(start, end, results, &wg)}wg.Wait()close(results)total := 0for result := range results {total += result}endTime := time.Now()fmt.Printf("Total number of primes: %d\n", total)fmt.Printf("Execution time: %v\n", endTime.Sub(startTime))
}
编译运行一下试试
golang 一下就赶上来了,成绩不错恭喜恭喜,速度还可以就是写法会麻烦了一些
看看net8 代码先上来,记得要编译release版本
using System;
using System.Diagnostics;namespace FindPrime
{class Program{static int CountPrimes(){const int maxNumber = 1000000;int primeCount = 0;bool[] isPrime = new bool[maxNumber + 1];for (int i = 2; i <= maxNumber; i++){isPrime[i] = true;}Parallel.For(2 , maxNumber + 1, i =>{for (int j = 2; j <= Math.Sqrt(i); j++){if (i % j == 0){isPrime[i] = false;break;}}});for (int i = 2; i <= maxNumber; i++){if (isPrime[i]){primeCount++;}}return primeCount;}static void Main(string[] args){Stopwatch timer = Stopwatch.StartNew();int result = CountPrimes();timer.Stop();Console.WriteLine($"The number of prime numbers is: {result}");Console.WriteLine($"Execution time: {timer.ElapsedMilliseconds:F4} ms");}}
}
跑起来看看,貌似负优化,其实之前在amd ryzen cpu上并行是比单线程快的,这个优化的不稳定
最后上boss,我们的python大佬要登场了,看看科学界的宠儿到底怎么样
import numpy as np
import timestart_time = time.perf_counter()# 创建包含所有整数的数组
numbers = np.arange(2, 1000000)# 创建布尔数组,初始化为 True
is_prime = np.ones(len(numbers), dtype=bool)# 筛选法标记非质数
for i in range(2, int(np.sqrt(1000000)) + 1):if is_prime[i - 2]:is_prime[i * 2 - 2::i] = False# 获取所有质数
primes = numbers[is_prime]# 打印质数
end_time = time.perf_counter()
time_elapsed = end_time - start_timeprint(f"The number of prime numbers is: {len(primes)}")
print(f"Execution time: {time_elapsed*1000:.4f}ms")
不编译exe了直接脚本跑,结果出来了,快golang10倍,所以说数值计算还是来python吧,没啥说的 散会