2013-05-17 2 views
0

Итак, этим утром я решил поиграть с бенчмаркингом в первый раз.Точность бенчмаркинга Ruby - Профилактика ветви на ее самом лучшем?

Мне было интересно узнать о скорости, отличной от кода с форматированием блока «do-end» против форматирования «{}».

Так что я сохранил Benchmark код в Proc, так что я мог бы назвать его несколько раз подряд:

n = 100_000_000 
bmp = Proc.new do 
    Benchmark.bm do |x| 
    x.report {n.times {a = "1"}} 
    x.report {n.times do; a = "1"; end} 
    end 
end 

Мои результаты мы ожидали, когда я побежал один раз.

>> bmp.call 
    user  system  total  real 
1.840000 0.030000 1.870000 ( 1.874507) 
1.860000 0.050000 1.910000 ( 1.926101) 
=> true 

Но затем снова запустил его.

>> bmp.call 
    user  system  total  real 
1.870000 0.050000 1.920000 ( 1.922810) 
1.840000 0.000000 1.840000 ( 1.850615) 

Для меня это выглядит как полная противоположность тому, что я ожидаю. Я знаком с концепцией отраслевого предсказания. Является ли это классическим примером отраслевого прогноза? Если нет, то что? Есть ли способ предотвратить любые неточности, подобные этому (если это даже считается одним)?

EDIT: Я использовал этот код более 30 раз, после некоторых предложений. Часто он чередовался между двумя результатами. Образец данных здесь:

gist.github.com/TheLarkInn/5599676

+0

Я скопировал ваш код и провел его сам, 30 раз, и не получал строгого чередования между результатами. Как двоичная строка (где 1 подтверждает вашу гипотезу о '{}' как-то быстрее, а 0 опровергает ее), я получил «00 11 10 00 10 10 01 00 11 01 00 11 11 00 11», что выглядит довольно случайным образом me –

ответ

3

Прежде всего, ваш тест совершенно бессмысленно. Разница между синтаксисом do/end и синтаксисом {/} такова: синтаксис. Семантической разницы нет. Ergo, там не может быть быть любой разницей производительности во времени между ними. Это просто нелогично. Вам не нужно сравнивать его.

Единственное различие в производительности, которое может существует, заключается в том, что требуется больше времени для анализа, чем для другого. Тем не менее, ни один из двух сложнее разобрать, чем другой. Единственное отличие - приоритет. Поэтому, скорее всего, это не разница в производительности при анализе.

И даже если там были разница в производительности при разборе, ваш контрольный показатель не показывал бы его. Вы используете тест, написанный на Ruby, но для запуска Ruby-кода механизм выполнения Ruby должен сначала проанализировать его, что означает, что синтаксический анализ уже произошел, прежде чем ваш тест начнется.Итак, даже если ваш контрольный показатель не был бессмысленным, все равно было бы бесполезным, так как он не может измерять разницу в производительности при разборе.

Что касается вашего вопроса о Прогнозирование ветвей: в вашем коде нет ветвей, предсказать нечего.

BTW: даже если ваш ориентир был предназначен для другой цели, он все равно ничего не будет измерять, поскольку, по крайней мере, более продвинутые реализации Ruby распознают, что ваши блоки по существу не являются операционными системами и просто оптимизируют их. И даже если они не оптимизированы, все они измеряют производительность распределительного устройства памяти (выделяя пару сотен мегабайт крошечных объектов String), а не производительность блоков.

+0

Чудесно положил. Цель теста заключалась в том, чтобы увидеть, существует ли разница во времени между выполнением кода с помощью {} vs. do/end. Спасибо за объяснение. Что касается Branch Prediction, у меня создалось впечатление, что он не только связан с ветвями в коде, но и является более общей идеей о том, что процессоры будут пытаться «угадать», что будет работать рядом с повышением производительности. –

1

Просто быстро праймер на статистике:

Я не уверен, что если два прохода достаточно, чтобы обнаружить тенденция. Что, если бы была разница в загрузке системы между двумя тестовыми блоками во второй раз, когда вы ее запускали?

Эмпирическое правило для определения статистической разницы между двумя образцами состоит в том, что 30 или более точек данных даст вам статистически релевантный результат.

Я бы проверил ваши тесты по крайней мере много раз, сохраняя результаты для двух версий самостоятельно, а затем сравните их внутри, чтобы убедиться, что они согласованы, прежде чем сравнивать два набора друг с другом.

Это может быть, что ваша первоначальная предпосылка неверна :)

+0

Системная нагрузка не должна быть основным фактором, я думаю, что «Benchmark» собирает тики процессов (так что только регистрирует то, что делает код, и довольно хорошо игнорирует другие процессы, хотя и не все), конкуренция все еще может возникать на диске, RAM и т. Д.). Тем не менее, это означает, что, несмотря на 100 миллионов повторений, в каждом тесте есть только ~ 190 булевых («процессор работает мой процесс»). Итак, основная часть вашего аргумента о статистике - это место. –

+0

Я делал это более 30 раз с теми же результатами. Каждый раз, когда вызывался proc, статистика перебрасывалась. –

+0

@Sean Larkin: Строгий флип, с точно такими же значениями каждый раз не будет статистической проблемой, а чем-то, лежащим в основе как разница. Но я скептически отношусь к вам, вы просто заглядываете в них и обнаруживаете образец, которого на самом деле нет? Не могли бы вы опубликовать свой пробег в 30 (может быть, он подходит), чтобы мы могли взглянуть? –

Смежные вопросы