net8正式版出来两个月,现在性能到底如何呢,做个简单的例子和其他语言比较一下,测试内容是查找1000000以内的质数,代码不多,但包含了循环计算和Math库函数调用,直观的看一下语言之间差距是多少,心里有个底,测试机是笔记本surface book 2 intel i7 有个四五年了,不过还能跑
单线程篇
首先来看看google的王牌语言golang,语法简单但性能号称不输C++,先看一下go 1.20.2
package main
import (
"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 := 0
for i := 2; i < n; i++ {
if isPrime(i) {
count++
}
}
return count
}
func main() {
num := 1000000
startTime := 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 False
for i in range(2, int(math.sqrt(num)) + 1):
if num % i == 0:
return False
return True
#@numba.jit
def count_primes(n):
count = 0
for i in range(2, n):
if is_prime(i):
count += 1
return count
num = 1000000
start_time = time.perf_counter()
result = count_primes(num)
end_time = time.perf_counter()
time_elapsed = end_time - start_time
print(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 main
import (
"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 := 0
for i := start; i < end; i++ {
if isPrime(i) {
count++
}
}
resultChan <- count
}
func main() {
startTime := time.Now()
num := 1000000
goroutines := 10
results := make(chan int, goroutines)
var wg sync.WaitGroup
wg.Add(goroutines)
step := num / goroutines
for i := 0; i < goroutines; i++ {
start := i * step
end := (i + 1) * step
if i == goroutines-1 {
end = num
}
go countPrimes(start, end, results, &wg)
}
wg.Wait()
close(results)
total := 0
for 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 time
start_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_time
print(f"The number of prime numbers is: {len(primes)}")
print(f"Execution time: {time_elapsed*1000:.4f}ms")
不编译exe了直接脚本跑,结果出来了,快golang10倍,所以说数值计算还是来python吧,没啥说的 散会