Cайт веб-разработчика, программиста Ruby on Rails ESV Corp. Екатеринбург, Москва, Санкт-Петербург, Новосибирск, Первоуральск
Стоит ли безоговорочно доверять тестам сравнения производительности языков программирования?
Стоит ли безоговорочно доверять тестам сравнения производительности языков программирования, скорости выполнения программ(benchmark, benchmarks) на популярных сайтах?
Более внимательное рассмотрение одного из тестов с сайта (которому многие привыкли доверять) сравнения производительности benchmarksgame.alioth.debian.org. Тест взят просто случайным образом (тот случай, где Ruby оказался медленее PHP) - тест mandelbrot.
Я написал простейшие тесты сравнения производительности для Ruby, написал точь-в-точь идентичные на PHP. На этих тестах PHP "одержал" сокрушительное поражение. И, о чудо, на сайте benchmarksgame.alioth.debian.org, которому многие привыкли безоговорочно доверять, обнаруживается, что PHP все еще на коне, да еще и очень опережает Ruby. Меня это очень заинтересовало. Как же так? Все оказалось совершенно просто - суть в реализации алгоритмов - если в тесте на PHP используются простейшие циклы, то в тесте Ruby используются итераторы - более медленный, хотя и более мощный механизм. В общем, все встало на свои места, по крайней мере для меня - Ruby быстрее PHP. Как сказал классик: "Мало ли чего можно рассказать! Не всему же надо верить."
Дабы не быть голословным, привожу исходники этого теста. Знатоки Ruby и PHP сразу заметят в чем тут соль, и почему Ruby вдруг оказался медленнее.
# The Computer Language Benchmarks Game
# http://benchmarksgame.alioth.debian.org
#
# contributed by Karl von Laudermann
# modified by Jeremy Echols
# modified by Detlef Reichl
# modified by Joseph LaFata
PAD = "\\\\__MARSHAL_RECORD_SEPARATOR__//" # silly, but works
class Worker
attr_reader :reader
def initialize(enum, index, total, &block)
@enum = enum
@index = index
@total = total
@reader, @writer = IO.pipe
if RUBY_PLATFORM == "java"
@t = Thread.new do
self.execute(&block)
end
else
@p = Process.fork do
@reader.close
self.execute(&block)
@writer.close
end
@writer.close
end
end
def execute(&block)
(0 ... @enum.size).step(@total) do |bi|
idx = bi + @index
if item = @enum[idx]
res = yield(item)
@writer.write(Marshal.dump([idx, res]) + PAD)
end
end
@writer.write(Marshal.dump(:end) + PAD)
end
end
def parallel_map(enum, worker_count = 8, &block)
count = [enum.size, worker_count].min
Array.new(enum.size).tap do |res|
workers = (0 ... count).map do |idx|
Worker.new(enum, idx, count, &block)
end
ios = workers.map { |w| w.reader }
while ios.size > 0 do
sr, sw, se = IO.select(ios, nil, nil, 0.01)
if sr
sr.each do |io|
buf = ""
while sbuf = io.readpartial(4096)
buf += sbuf
break if sbuf.size < 4096
end
msgs = buf.split(PAD)
msgs.each do |msg|
m = Marshal.load(msg)
if m == :end
ios.delete(io)
else
idx, content = m
res[idx] = content
end
end
end
end
end
Process.waitall
end
end
$size = (ARGV[0] || 100).to_i
csize = $size - 1
puts "P4"
puts "#{$size} #{$size}"
set = (0 ... $size).to_a
results = parallel_map(set, 8) do |y|
res = ""
byte_acc = 0
bit_num = 0
ci = (2.0 * y / $size) - 1.0
$size.times do |x|
zrzr = zr = 0.0
zizi = zi = 0.0
cr = (2.0 * x / $size) - 1.5
escape = 0b1
50.times do
tr = zrzr - zizi + cr
ti = 2.0 * zr * zi + ci
zr = tr
zi = ti
# preserve recalculation
zrzr = zr * zr
zizi = zi * zi
if zrzr + zizi > 4.0
escape = 0b0
break
end
end
byte_acc = (byte_acc << 1) | escape
bit_num += 1
if (bit_num == 8)
res += byte_acc.chr
byte_acc = 0
bit_num = 0
elsif (x == csize)
byte_acc <<= (8 - bit_num)
res += byte_acc.chr
byte_acc = 0
bit_num = 0
end
end
res
end
print results.join
Вот тот же самый тест, но уже написанный полностью идентично на Ruby и PHP, в котором все встало на свои места.
Стоит ли безоговорочно доверять тестам сравнения производительности языков программирования, скорости выполнения программ (benchmark, benchmarks) на популярных сайтах?
Более внимательное рассмотрение одного из тестов с сайта (которому многие привыкли доверять) сравнения производительности benchmarksgame.alioth.debian.org. Тест взят просто случайным образом (тот случай, где Ruby оказался медленее PHP) - тест mandelbrot.
Я написал простейшие тесты сравнения производительности для Ruby, написал точь-в-точь идентичные на PHP. На этих тестах PHP "одержал" сокрушительное поражение. И, о чудо, на сайте benchmarksgame.alioth.debian.org, которому многие привыкли безоговорочно доверять, обнаруживается, что PHP все еще на коне, да еще и очень опережает Ruby. Меня это очень заинтересовало. Как же так? Все оказалось совершенно просто - суть в реализации алгоритмов - если в тесте на PHP используются простейшие циклы, то в тесте Ruby используются итераторы - более медленный, хотя и более мощный механизм. В общем, все встало на свои места, по крайней мере для меня - Ruby быстрее PHP. Как сказал классик: "Мало ли чего можно рассказать! Не всему же надо верить."
Дабы не быть голословным, привожу исходники этого теста. Знатоки Ruby и PHP сразу заметят в чем тут соль, и почему Ruby вдруг оказался медленнее.
PHP:
Ruby:
Вот тот же самый тест, но уже написанный полностью идентично на Ruby и PHP, в котором все встало на свои места.