Google Go vs. Си
Ребята на работе как-то спонтанно решили померить языки программирования на каком-нибудь несложном алгоритме. Для сравнения выбрали решето Эратосфена для поиска простых чисел (правда, первая реализация получилась неотимальная и с некритичной ошибкой, но мы решили дословно повторить этот вариант на всех остальных языках).
Я подключился и написал пример на Google Go:
package main
import "fmt"
func main() {
x := []int{2}
for i := 3; i < 200000; i += 2 {
simple := true
for _, j := range x {
if i % j == 0 {
simple = false
break
}
}
if simple {
x = append(x, i)
}
}
fmt.Println(x)
}
Запускалось всё на каком-то ноутбуке MacBook Pro. Результаты несколько неожиданные:
Python — 25,95 секунды Perl — 22,96 секунды PHP — 21 секунда Objective C — 9,40 секунды JavaScript (V8) — 4,73 секунды Java — 1,94 секунды Си — 0.95 секунды Google Go — 0,71 секунды.
Особенно меня поразили «Гоу» и JavaScript.
я конечно понимаю, новые тренды, все такое, но в большенстве браузеров, твой блог без джса и цсса, а то что он в 1м или в 2ух как нужно — это ЛАЖА... короче, это не правильно
Комментарий для deerua:
Я не понимаю причём тут новые тренды. Я проверил свой блог на браузерах с сайта BrowserShots ( http://browsershots.org/ ), там везде (кроме Dillo) сайт отображается нормально.
Если ты мне напишешь (и без этого хамства) в каком браузере что-то не отображается (и лучше в подходящем для этого месте — заметке, где я написал про JS+CSS), я попробую поправить.
Цифры удивили, если честно. Но для полной картины наверное все исходники надо выложить ;)
Результаты несолько неожиданные:
буква «К» в слове «несолько» пропущена :)
А тексты программ можешь выложить? И версии интерпретаторов. Меня тоже perl удивил, вроде как уж у кого, должно быть с производительностью ок, так это у него.
Интересно ещё было бы запустить на JavaScript. На маке уже вроде во всех браузерах JIT.
Для компиляции Go использовался gccgo или 6g?
Комментарий для vitaly:
6g.
Комментарий для libc6.org:
perl 5.10 http://pastebin.com/6ejFTcrH
python 2.6.1 http://pastebin.com/v6WR4CpE
других у меня пока нет, попрошу ребят, которые писали, сюда положить
Комментарий для greli.livejournal.com:
Зачем браузеры? Можно поставить V8 (brew install v8)
Я программу уже написал:
V8 version 3.4.6.2 http://pastebin.com/tdXTwv0s
Но парень, у которого «эталонный» Мак (на котором мы всё пускали), едет домой, приедет, запустит :)
Ого. Вот так новости. Ну это вааааще.
Евгений, в Perl нет break, используйте last. Использованный вами в тестировании скрипт работал неверно — вложенный цикл не прерывался.
Исправленный скрипт отрабатывает 23 секунду, то есть быстрее чем на Python.
http://pastebin.com/TLnpZXgp
Опечатался: Perl-скрипт отрабатывает за 21 секунду.
Комментарий для blog.chaotics.org:
Сергей, а вы обладатель того самого эталонного ноутбука, на котором проводились тесты?
Комментарий для blog.chaotics.org:
Спасибо! Не я писал этот скрипт, правда, я проверял, но взгляд за break не зацепился. Попрошу обладателя эталонного ноутбука перезапустить тест.
С# бы ещё посмотреть.
Есть целый проект исследования производительности языков. Судя по нему, Go по всем тестам оказывается медленнее Си.
http://shootout.alioth.debian.org/u32/benchmark.php?test=all%26lang=go%26lang2=gcc
Комментарий для Александр Карпинский:
Должен бы. Странно почему тут обогнал.
Комментарий для Евгения Степанищева:
Версия на js неожиданно быстрее всего выполняется в Сафари, 2,8 сек. Потом ФФ, за 3,3 сек. В Опере, Хроме и ИЕ примерно поровну — 4,4. Хорошо браузеры прокачались в числодробилках :)
Комментарий для Александр Карпинский:
Завтра посмотрим как выполняется версия на JS под нашим эталонным Маком :) «Опера» последняя бралась? 11.50RC1?
Комментарий для Евгения Степанищева:
Да.
Комментарий для Saper:
Ну, пустить его под Маком, кажется, нетривиальная задача. Да и эксперимент будет нечестным — для C# это чужеродная среда.
Всем привет.
Выкладываю все исходники!
Plain C: http://pastie.textmate.org/private/zpslsfmt6hg0u3tsgkx5w
Google Go: http://pastie.textmate.org/private/5o7zhky3ltajtq3dx253g
Java: http://pastie.textmate.org/private/hmjjn5m64evaxwkpnmxxq
JavaScript: http://pastie.textmate.org/private/v287gwfe1sowpcl9d9qda
ObjC: http://pastie.textmate.org/private/mvb25krmxvu1amegzclq
PHP: http://pastie.textmate.org/private/pq3ss3kxgbcvcktc0mug
Perl: http://pastie.textmate.org/private/bbpcwcj5ccnk7ircjifa
Python: http://pastie.textmate.org/private/rjqtcdmqoherjjw5bxmyg
Исправленная версия на перле работала 22.96 сек (а я собственно обладатель эталонного макбука) — спасибо Сергею))
JavaScript(V8) — 4.73 сек.
ObjC — 9.40, но это конечно стеб. Я ее написал просто для кучи, разумеется можно было просто скормить Plain C версию Xcode.
Пересмотрел исходники и вдруг понял, что я не просто так пишу на python. Правильный язык.
Спасибо, Миш!
JS добавил, несправедливость с Перлом пофиксил.
Комментарий для mixael:
Кстати, у Володи есть версия на C++, завтра и её надо будет потестировать, но там что-то не очень впечатляющее по скорости получается, судя по всему.
Ну раз уж пошли доработки — доработайте немного php-версию. Вынесите count из for — прирост на моем ноуте примерно 33%.
И таки да — даже в 2011 году php не может нормально обрабатывать циклы =(
Упс, ошибка. Прирост составил примерно 66%, а не 33. Т. е. по скорости получится так же, как и питон/перл, возможно чуть быстрее.
Комментарий для aktuba:
Положите на pastebin.com ваш вариант, Миша запустит как увидит комментарий.
А зачем PHP так замучили? Требую реабилитации!
http://pastie.textmate.org/private/eovr5vhhyynup4qabp63a
http://pastebin.com/zHZxrw05
Не удобно с айфона набирать )
Вариант Сергея, кстати, лучше. Но не думаю, что сильно поможет, если честно.
Какие-то странные у вас реализации. До того, чтобы перебирать только четные числа додумались, а до того, чтобы ограничить перебор делителей корнем из тестируемого числа — нет?
Хочется С++ и фортран для счастья
Комментарий для Сергей:
Оптимизация ни к чему. Нужно переписать код как есть.
Комментарий для eyeless:
Вы про кого говорите? Кто додумался? Я написал: «правда, первая реализация получилась неотимальная и с некритичной ошибкой, но мы решили дословно повторить этот вариант на всех остальных языках». Читайте внимательно, пожалуйста.
И, кстати, вам не всё равно какой абстрактный алгоритм является пузомеркой? Вы что, верите, что стоит реализовать правильный алгоритм и, скажем, Perl выйдет на первое место или что? Или вы эти реализации планируете у себя в коде использовать?
Комментарий для zitter:
C++ будет, а Фортран у нас не знает никто.
PHP в варианте Сергея 17сек.
А на фортране я писал когда-то) Тока где бы найти компилятор под Mac OS X
Комментарий для mixael:
Ну, это читерство — так оптимизировать, на всех языках можно так сделать :) Испытай лучше вот этот: http://pastebin.com/zHZxrw05 А С++ ты у Володи Москвы не взял?
http://r.research.att.com/tools/ Он есть в brew.
php 21 сек
А мой вариант замерили? Алгоритм то тот же?
Упс, не увидел сразу. Ускорение в 2.5 раза на одном count... Пора менять php на node.js
а чем именно мерились? временем работы алгоритма, взаимодействием с выводом или компиляцией в байткод (где это нужно)? и как делались замеры времени?
со скуки (в интернете кто-то неправ :) ) померил на неэталонном mbp:
java (замер времени через time): 1.44s
java (замер времени в коде чтоб исключить время компиляции в байткод, System.nanoTime()-start): 1,15s
java (замер времени в коде и убран вывод на экран): 0.74s
plain c (замер через time): 0.89s
plain c (замер через time и убран вывод на экран): 0.88s
несколько неожиданно если судить по скорости работы только алгоритма
Комментарий для artemp.pip.verisignlabs.com:
Холодный запуск. Утилита time.
Утилита time.
Зачем нужно убирать время компиляции и убирать вывод на экран, если первое всё равно чувствительно для пользователя, а второе есть в задаче?
Да кому оно интересно, голое время работы алгоритма?
На всякий случай сюда тоже напишу, что этот алгоритм — не решето Эратосфена. В классическом решете нет деления с остатком.
Комментарий для Евгения Степанищева:
Первое чуствительно для пользователя, если он перед каждым запуском функции компилирует в байткод. Это может быть и не так, если у него процесс в памяти висит, и выполняет много задач подряд, а не одну.
Возможно потому, что если ваша задача выполняется не 0.5 секунды, а хотя бы минуту, то время компиляции будет вносить значительно меньшую погрешность.
Вот мой вариант на С++
http://pastie.textmate.org/private/xhet0zuufqo3yhfyic6ga
у меня с С разницы по скорости 0 (gcc 4.4.5)
Комментарий для Евгения Степанищева:
там в PHP основной выигрыш от замены for на foreach (PHP что — то долго элемент массива по индексу берёт, ручной count не сильно помогает) а continue — это так уж, меж делом :)
Комментарий для fulc.ru:
Эту разницу я, конечно же, понимаю.
Комментарий для Евгения Степанищева:
А почему не логично не учитывать время компиляции? Почему мы не учитываем время работы gcc в замерах производительности c?
Комментарий для fulc.ru:
Потому что запускаемой программой на этих языках считаются разные вещи. На компилируемых — скомпилированная, на интерпретируемых — исходный код.
С++ — 0,82. http://pastebin.com/p3c6MJp0
Комментарий для Евгения Степанищева:
Поскольку я вижу в самой заметке:
Чтобы померить время холодного старта достаточно hello world, к чему городить огород с алгоритмом? Только вот к языкам программирования это не имеет ни малейшего отношения. И, кстати, подсчет времени в коде я углядел в php версии. По-моему кто-то что-то недоговаривает :)
Опять же:
Не думаю что вывод на экран имеет отношение к поиску простых чисел. Если бы выбрали для сравнения вывод n чисел на экран тогда другое дело.
PS: разумеется компиляция не в байткод а из него.
Комментарий для Евгения Степанищева:
Хотя, если
тогда конечно да. Мерить языки программирования временем старта интерпретатора/виртуальной машины и компиляции/интерпретации куда как увлекательнее. Особенно в сравнении с теми языками где оных нет.
Комментарий для artemp.pip.verisignlabs.com:
Понятно, что интерпретируемые будут медленнее, вопрос не в этом, интересно насколько. При этом мы видим, что Java и JavaScript — это секунды, а остальные интерпретаторы — десятки секунд.
Комментарий для artemp.pip.verisignlabs.com:
Не нужно относиться к этому как к серьёзному исследованию. Нам хотелось немного повеселиться, заодно посмотреть насколько различается холодное время выполнения разных языков.
По поводу разницы старта скомпилированных программ и интерпретируемых с интерпретатором.
Некоторыми комментаторам предлагает исключить время старта виртуальной машины/разбора кода и прочее. Странно, но никто не предложил сделать то же со скомпилированными программами.
У них тоже есть время старта (чтение с диска), инициализации (заполнение различных значений, например, переменных окружения), загрузка библиотек (например, моя программа makecorner использует libgd.2.0.0.dylib и libSystem.B.dylib, те в свою очередь используют ещё что-то). Что за дискриминация? :)
Комментарий для Евгения Степанищева:
нас хлебом не корми, дай копья поломать :)
никакой дискриминации, согласен с предложением.
более того, полагаю что выигрыш во времени у java версии по сравнению с си в моем сравнении вероятно именно этим и обусловлен. я действительно был удивлен результатами. к сожалению я не на короткой ноге с си, поэтому не добавил подсчет времени в код си версии. но с удовольствием бы взглянул на результаты сравнения голых алгоритмов (и всё-таки я против вывода на экран :) )
Комментарий для artemp.pip.verisignlabs.com:
Ну так за чем дело встало? Компиляторы-то для всех платформ существуют :)
А частота процессора была всего одна и та же у эталонного ноутбука?
По умолчанию система может произвольно менять частоту. Допустим, Go исполнялся на 2.5 GHz, а C — на 2.
Комментарий для maxim-zotov.livejournal.com:
Не могу сказать. Но Миша, который тестировал, знатный маковод. Спрошу у него как увижу на работе или в джаббере.
Вообще, мы программы подряд пускали и несколько раз вперемешку (не могли глазам поверить), поэтому вряд ли.
В Go не силён — как компилировали? Я разницы в скорости между Си и Go не получил (x86-64). (Go — 6g+6l использовал, для C — gcc 4.5 и 4.6 пробовал)
Комментарий для Nick:
Гоу компилировался при помощи 6g и 6l, чем Миша компилировал программу на Си я не знаю, но подозреваю, что тем gcc, что стоит в Мак ОСи, тут это gcc 4.2.1 (Apple Inc. build 5666) (dot 3)
Комментарий для Евгения Степанищева:
Никаких дополнительных опций оптимизации? Тогда это скорее проблема gcc 4.2. Не думаю, что дело в ОС (у меня GNU/Linux).
Комментарий для Nick:
Никаких, да.
Комментарий для Евгения Степанищева:
Можно и не компилировать самому:
— JavaScript (Rhino): http://ideone.com/Z3e1T — время: 2.53 s, память: 214016 kB
— JavaScript (SpiderMonkey): http://ideone.com/E62qk — время: 1.08 s, память: 5076 kB
— Perl: http://ideone.com/sBs9y — время: 0.34 s, память: 4732 kB
— С: http://ideone.com/7VWx7 — время: 0.04 s, память: 1908 kB
— Go: не запустился (undefined: append)
Я сократил количество итераций до 20000, иначе для некоторых языков время выполнения превышало лимит.
Комментарий для dionys.myopenid.com:
У них какой-то очень древний компилятор, поэтому интереса в этом мало :(
Комментарий для Евгения Степанищева:
Зато другие языки можно сравнить. Вон JavaScript уже не столь хорош.
Комментарий для dionys.myopenid.com:
Тоже ведь неизвестно что там за версия. Ну и V8 лучший из открытых.
Комментарий для Евгения Степанищева:
Почему неизвестно? Версия указана.
Комментарий для dionys.myopenid.com:
И правда.
На сайте SpiderMonkey версии 1.7, актуальную мне посмотреть не удалось, сайт лежит, но у меня в портах есть 1.8.5
На сайте Rhine версии 1.6.5, актуальная —1.7R3.
По меркам интерпретаторов JS — старьё. :)
http://www.opennet.ru/opennews/art.shtml?num=31114
for($j=0; $j<count($x); $j++)
стандартная ошибка, каунт пересчитывается на каждой итерации
надо писать
for($j=0 $max = count($x),$j<$max; $j++)
Комментарий для shaggyboy:
Нет тут никакой ошибки.
Задачи сделать максимально быстро нет. Есть задача повторить тот же алгоритм на разных языках.
А вот и на Ruby
тестить желательно на 1.9.2
http://pastebin.com/xHbRKnmk
Python test:
CPython — 12.11 sec
PyPy — 1.266 sec
/trollface
Комментарий для he1gus.livejournal.com:
Сейчас уже не смогу потестить, «эталонная» машина за много сотен километров.
Почему?
Этот код JS можно ускорить. Опубликовать вариант не могу, так как эти примочки являются сильной стороной нового фрэймворка, который вскоре выйдет на рынок.
Комментарий для proger:
Я несколько раз написал, что ничего ускорять не надо.
Я тут начал изучать Forth и первой программой написал тот же самый алгоритм, чтобы сравнить перфоманс.
http://hastebin.com/raw/fiqigusano
Использовал gforth и сравнивал с вашими программами на си и питоне.
man gforth:
x := []int{2}
for i := 3; i < 200000; i += 2 {
for _, j := range x {
if i%j == 0 {
break
}
}
x = append(x, i)
}
println(x)
Хорошо, что я нашёл этот пост. В случае Си «ларчик просто открывался», сейчас я уже плохо помню, но мы все примеры компилили на «Маке» и, похоже, по-умолчанию они компилировались llvm-gcc.
Вообще то да, это не решето решето Эратосфена.
Вот мои результаты питона (так как я пишу на нем)
И результаты с Гоу (так как хочу его изучать)
cорри за некропост -- не смог удержаться... perl тоже может быть достаточно быстр и короток в записи.... этот вариант быстрее предыдущего варианта на 1/3 -- из-за перехода «next LABEL» + выкинул лишние переменные + уменьшил накладные расходы на инициализацию областей видимости блоков ( вход в фигурные скобки в perl’е иногда бывает дорог;))) ).
#!/usr/bin/perl
use strict;
my @a = (2);
L: for (my $i = 3; $i <= 200_000; $i += 2) {
for (@a) {
next L unless $i % $_
}
push @a, $i
}
$, = ’, ’;
print @a;
Комментарий для gzim9x:
Ага, спасибо :) Когда-то я несколько лет на Перле программировал :) Но с тех пор много воды утекло. Читаю до сих пор свободно, а что-то писать уже тяжеловато :)