Ruby与C#性能对比分析

编程语言的世界中,性能始终是开发者关注的焦点之一。尽管C#通常被认为在性能上优于Ruby,但这种差距究竟有多大,一直是许多开发者心中的疑问。本文旨在通过实际的代码测试,探索Ruby与C#在执行相同任务时的性能差异。

为了进行这一比较,选择了几种不同的算法实现:暴力算法、埃拉托斯特尼筛法和桑德拉姆筛法。这些算法被广泛应用于计算素数,是测试性能的不错选择。

实验环境与方法

实验在Ubuntu操作系统上进行,使用了Virtual Box虚拟机,配置为2GB内存和3个处理器。首先参考了Ashraff Ali Wahab的文章,获取了C#的源代码。然后,尝试使用Ruby实现相同的算法,并运行测试。

源代码

以下是C#和Ruby的源代码实现:

// C#源代码请参考Ashraff Ali Wahab的文章 // Ruby暴力算法实现 def BruteForce(topCandidate) totalCount = 1 isPrime = true (3..step(topCandidate, 2)).each do |i| j = 3 while j * j <= i && isPrime isPrime = false if i % j == 0 j += 2 end totalCount += 1 if isPrime isPrime = true end totalCount end // Ruby埃拉托斯特尼筛法实现 def SieveOfEratosthenes(topCandidate) myBA1 = Array.new(topCandidate + 1, true) myBA1[0] = myBA1[1] = false thisFactor = 2 while thisFactor * thisFactor <= topCandidate mark = thisFactor + thisFactor (mark..step(topCandidate, thisFactor)).each { |n| myBA1[n] = false } thisFactor += 1 while !myBA1[thisFactor] thisFactor += 1 end myBA1.count(true) end // Ruby桑德拉姆筛法实现 def SieveOfSundaram(topCandidate) k = topCandidate / 2 myBA1 = Array.new(k + 1, true) myBA1[0] = myBA1[k] = false (1..k).each do |i| denominator = (i << 1) + 1 maxVal = (k - i) / denominator (i..step(maxVal+1, 1)).each { |n| myBA1[i + n * denominator] = false } end myBA1.count(true) + 1 end // 主程序 def main max = 1000000 startTime = Time.now() primes = BruteForce(max) endTime = Time.now() elapsed = endTime - startTime puts "Elapsed time for Brute Force: #{elapsed} Primes = #{primes}" startTime = Time.now() primes = SieveOfEratosthenes(max) endTime = Time.now() elapsed = endTime - startTime puts "Elapsed time for Sieve of Eratosthenes: #{elapsed} Primes = #{primes}" startTime = Time.now() primes = SieveOfSundaram(max) endTime = Time.now() elapsed = endTime - startTime puts "Elapsed time for Sieve of Sundaram: #{elapsed} Primes = #{primes}" end

测试结果

从测试结果可以看出,Ruby在执行暴力算法时大约比C#慢5倍,在执行埃拉托斯特尼筛法和桑德拉姆筛法时大约慢19倍。这一结果与之前提到的网站数据基本一致。

遗憾的是,IronRuby的测试没有完成,程序在执行过程中失败了。

虽然这次测试并不完全,但它提供了一些有价值的见解。特别是Ruby代码中的注释部分:

# 这个版本的for循环比step函数慢了50%! (1..maxVal+1).each do |n| # myBA1[i + n * denominator] = false end

这表明,尽管理论上block {|n| myBA1[i + n * denominator] = false} 是作为函数调用实现的,但step函数作为库实现(很可能是编译过的),其性能优势是显著的。

IronRuby代码的失败令人失望,原本期望这种“简单”的任务不会遇到问题。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485