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.

Комментарии 86

deerua № 1
я конечно понимаю, новые тренды, все такое, но в большенстве браузеров, твой блог без джса и цсса, а то что он в 1м или в 2ух как нужно — это ЛАЖА… короче, это не правильно
Евгений Степанищев (bolknote.ru) автор № 2
я конечно понимаю, новые тренды, все такое, но в большинстве браузеров, твой блог без джса и цсса, а то что он в 1м или в 2ух как нужно — это ЛАЖА… короче, это не правильно

Я не понимаю причём тут новые тренды. Я проверил свой блог на браузерах с сайта BrowserShots ( http://browsershots.org/ ), там везде (кроме Dillo) сайт отображается нормально.

Если ты мне напишешь (и без этого хамства) в каком браузере что-то не отображается (и лучше в подходящем для этого месте — заметке, где я написал про JS+CSS), я попробую поправить.

librarian (libc6.org) № 5
А тексты программ можешь выложить? И версии интерпретаторов. Меня тоже perl удивил, вроде как уж у кого, должно быть с производительностью ок, так это у него.
greli (greli.livejournal.com) № 6
Интересно ещё было бы запустить на JavaScript. На маке уже вроде во всех браузерах JIT.
Евгений Степанищев (bolknote.ru) автор № 10
Интересно ещё было бы запустить на JavaScript. На маке уже вроде во всех браузерах JIT.

Зачем браузеры? Можно поставить V8 (brew install v8)

Я программу уже написал:
V8 version 3.4.6.2 http://pastebin.com/tdXTwv0s

Но парень, у которого «эталонный» Мак (на котором мы всё пускали), едет домой, приедет, запустит :)

Sergey Palyanov (blog.chaotics.org) № 12
Евгений, в Perl нет break, используйте last. Использованный вами в тестировании скрипт работал неверно — вложенный цикл не прерывался.

Исправленный скрипт отрабатывает 23 секунду, то есть быстрее чем на Python.
http://pastebin.com/TLnpZXgp
Александр Карпинский № 14
Комментарий для blog.chaotics.org:

Сергей, а вы обладатель того самого эталонного ноутбука, на котором проводились тесты?
Евгений Степанищев (bolknote.ru) автор № 15

Комментарий для blog.chaotics.org:

Евгений, в Perl нет break, используйте last. Использованный вами в тестировании скрипт работал неверно — вложенный цикл не прерывался.

Спасибо! Не я писал этот скрипт, правда, я проверял, но взгляд за break не зацепился. Попрошу обладателя эталонного ноутбука перезапустить тест.

Евгений Степанищев (bolknote.ru) автор № 18

Комментарий для Александр Карпинский:

Судя по нему, Go по всем тестам оказывается медленнее Си.

Должен бы. Странно почему тут обогнал.

Александр Карпинский № 19
Комментарий для Евгения Степанищева:

Версия на js неожиданно быстрее всего выполняется в Сафари, 2,8 сек. Потом ФФ, за 3,3 сек. В Опере, Хроме и ИЕ примерно поровну — 4,4. Хорошо браузеры прокачались в числодробилках :)
Евгений Степанищев (bolknote.ru) автор № 20
Комментарий для Александр Карпинский:

Завтра посмотрим как выполняется версия на JS под нашим эталонным Маком :) «Опера» последняя бралась? 11.50RC1?
mixael № 23
Всем привет.
Выкладываю все исходники!
Plain C: http://pastie.textmate.org/private/zpslsfm … 0u3tsgkx5w
Google Go: http://pastie.textmate.org/private/5o7zhky … jtq3dx253g
Java: http://pastie.textmate.org/private/hmjjn5m … axwkpnmxxq
JavaScript: http://pastie.textmate.org/private/v287gwf … wpcl9d9qda
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/rjqtcdm … rjjw5bxmyg

Исправленная версия на перле работала 22.96 сек (а я собственно обладатель эталонного макбука) — спасибо Сергею))
JavaScript(V8) — 4.73 сек.
ObjC — 9.40, но это конечно стеб. Я ее написал просто для кучи, разумеется можно было просто скормить Plain C версию Xcode.
Евгений Степанищев (bolknote.ru) автор № 26
Комментарий для mixael:

Кстати, у Володи есть версия на C++, завтра и её надо будет потестировать, но там что-то не очень впечатляющее по скорости получается, судя по всему.
aktuba № 27
Ну раз уж пошли доработки — доработайте немного php-версию. Вынесите count из for — прирост на моем ноуте примерно 33%.
И таки да — даже в 2011 году php не может нормально обрабатывать циклы =(
Сергей № 30
А зачем PHP так замучили? Требую реабилитации!
http://pastie.textmate.org/private/eovr5vh … up4qabp63a
Евгений Степанищев (bolknote.ru) автор № 34
А зачем PHP так замучили? Требую реабилитации!

Оптимизация ни к чему. Нужно переписать код как есть.

eyeless № 32
Какие-то странные у вас реализации. До того, чтобы перебирать только четные числа додумались, а до того, чтобы ограничить перебор делителей корнем из тестируемого числа — нет?
Евгений Степанищев (bolknote.ru) автор № 35
Какие-то странные у вас реализации. До того, чтобы перебирать только четные числа додумались, а до того, чтобы ограничить перебор делителей корнем из тестируемого числа — нет?

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

И, кстати, вам не всё равно какой абстрактный алгоритм является пузомеркой? Вы что, верите, что стоит реализовать правильный алгоритм и, скажем, Perl выйдет на первое место или что? Или вы эти реализации планируете у себя в коде использовать?

Евгений Степанищев (bolknote.ru) автор № 38

Комментарий для mixael:

PHP в варианте Сергея 17сек.

Ну, это читерство — так оптимизировать, на всех языках можно так сделать :) Испытай лучше вот этот: http://pastebin.com/zHZxrw05 А С++ ты у Володи Москвы не взял?

А на фортране я писал когда-то) Тока где бы найти компилятор под Mac OS X

http://r.research.att.com/tools/ Он есть в brew.

artemp.pip.verisignlabs.com № 42
а чем именно мерились? временем работы алгоритма, взаимодействием с выводом или компиляцией в байткод (где это нужно)? и как делались замеры времени?

со скуки (в интернете кто-то неправ :) ) померил на неэталонном mbp:

java (замер времени через time): 1.44s
java (замер времени в коде чтоб исключить время компиляции в байткод, System.nanoTime()-start): 1,15s
java (замер времени в коде и убран вывод на экран): 0.74s

plain c (замер через time): 0.89s
plain c (замер через time и убран вывод на экран): 0.88s

несколько неожиданно если судить по скорости работы только алгоритма
Евгений Степанищев (bolknote.ru) автор № 43
а чем именно мерились? временем работы алгоритма, взаимодействием с выводом или компиляцией в байткод (где это нужно)?

Холодный запуск. Утилита time.

и как делались замеры времени?

Утилита time.

java (замер времени в коде чтоб исключить время компиляции в байткод, System.nanoTime()-start): 1,15s ava (замер времени в коде и убран вывод на экран): 0.74s

Зачем нужно убирать время компиляции и убирать вывод на экран, если первое всё равно чувствительно для пользователя, а второе есть в задаче?

несколько неожиданно если судить по скорости работы только алгоритма

Да кому оно интересно, голое время работы алгоритма?

Vladimir Moskva (fulc.ru) № 44
На всякий случай сюда тоже напишу, что этот алгоритм — не решето Эратосфена. В классическом решете нет деления с остатком.
Vladimir Moskva (fulc.ru) № 45

Комментарий для Евгения Степанищева:

Зачем нужно убирать время компиляции и убирать вывод на экран, если первое всё равно чувствительно для пользователя, а второе есть в задаче?

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

whtiger № 46
Зачем нужно убирать время компиляции и убирать вывод на экран, если первое всё равно чувствительно для пользователя, а второе есть в задаче?

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

Сергей № 48
Комментарий для Евгения Степанищева:

там в PHP основной выигрыш от замены for на foreach (PHP что — то долго элемент массива по индексу берёт, ручной count не сильно помогает) а continue — это так уж, меж делом :)
Евгений Степанищев (bolknote.ru) автор № 49

Комментарий для fulc.ru:

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

Эту разницу я, конечно же, понимаю.

Vladimir Moskva (fulc.ru) № 50
Комментарий для Евгения Степанищева:

А почему не логично не учитывать время компиляции? Почему мы не учитываем время работы gcc в замерах производительности c?
Евгений Степанищев (bolknote.ru) автор № 51

Комментарий для fulc.ru:

А почему не логично не учитывать время компиляции? Почему мы не учитываем время работы gcc в замерах производительности c?

Потому что запускаемой программой на этих языках считаются разные вещи. На компилируемых — скомпилированная, на интерпретируемых — исходный код.

artemp.pip.verisignlabs.com № 53

Комментарий для Евгения Степанищева:

Зачем нужно убирать время компиляции и убирать вывод на экран, если первое всё равно чувствительно для пользователя, а второе есть в задаче?

Поскольку я вижу в самой заметке:

померить языки программирования на каком-нибудь несложном алгоритме

Чтобы померить время холодного старта достаточно hello world, к чему городить огород с алгоритмом? Только вот к языкам программирования это не имеет ни малейшего отношения. И, кстати, подсчет времени в коде я углядел в php версии. По-моему кто-то что-то недоговаривает :)

Опять же:

Для сравнения выбрали решето Эратосфена для поиска простых чисел

Не думаю что вывод на экран имеет отношение к поиску простых чисел. Если бы выбрали для сравнения вывод n чисел на экран тогда другое дело.

PS: разумеется компиляция не в байткод а из него.

artemp.pip.verisignlabs.com № 54

Комментарий для Евгения Степанищева:

Хотя, если

Да кому оно интересно, голое время работы алгоритма?

тогда конечно да. Мерить языки программирования временем старта интерпретатора/виртуальной машины и компиляции/интерпретации куда как увлекательнее. Особенно в сравнении с теми языками где оных нет.

Евгений Степанищев (bolknote.ru) автор № 55

Комментарий для artemp.pip.verisignlabs.com:

тогда конечно да. Мерить языки программирования временем старта интерпретатора/виртуальной машины и компиляции/интерпретации куда как увлекательнее. Особенно в сравнении с теми языками где оных нет.

Понятно, что интерпретируемые будут медленнее, вопрос не в этом, интересно насколько. При этом мы видим, что Java и JavaScript — это секунды, а остальные интерпретаторы — десятки секунд.

Евгений Степанищев (bolknote.ru) автор № 56

Комментарий для artemp.pip.verisignlabs.com:

Чтобы померить время холодного старта достаточно hello world, к чему городить огород с алгоритмом? Только вот к языкам программирования это не имеет ни малейшего отношения. И, кстати, подсчет времени в коде я углядел в php версии. По-моему кто-то что-то недоговаривает :)

Не нужно относиться к этому как к серьёзному исследованию. Нам хотелось немного повеселиться, заодно посмотреть насколько различается холодное время выполнения разных языков.

Евгений Степанищев (bolknote.ru) автор № 57
По поводу разницы старта скомпилированных программ и интерпретируемых с интерпретатором.

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

У них тоже есть время старта (чтение с диска), инициализации (заполнение различных значений, например, переменных окружения), загрузка библиотек (например, моя программа makecorner использует libgd.2.0.0.dylib и libSystem.B.dylib, те в свою очередь используют ещё что-то). Что за дискриминация? :)
artemp.pip.verisignlabs.com № 58

Комментарий для Евгения Степанищева:

Не нужно относиться к этому как к серьёзному исследованию

нас хлебом не корми, дай копья поломать :)

Что за дискриминация? :)

никакой дискриминации, согласен с предложением.
более того, полагаю что выигрыш во времени у java версии по сравнению с си в моем сравнении вероятно именно этим и обусловлен. я действительно был удивлен результатами. к сожалению я не на короткой ноге с си, поэтому не добавил подсчет времени в код си версии. но с удовольствием бы взглянул на результаты сравнения голых алгоритмов (и всё-таки я против вывода на экран :) )

Евгений Степанищев (bolknote.ru) автор № 59

Комментарий для artemp.pip.verisignlabs.com:

но с удовольствием бы взглянул на результаты сравнения голых алгоритмов (и всё-таки я против вывода на экран :) )

Ну так за чем дело встало? Компиляторы-то для всех платформ существуют :)

Максим Зотов (maxim-zotov.livejournal.com) № 60
А частота процессора была всего одна и та же у эталонного ноутбука?
По умолчанию система может произвольно менять частоту. Допустим, Go исполнялся на 2.5 GHz, а C — на 2.
Евгений Степанищев (bolknote.ru) автор № 61
А частота процессора была всего одна и та же у эталонного ноутбука?

Не могу сказать. Но Миша, который тестировал, знатный маковод. Спрошу у него как увижу на работе или в джаббере.

Вообще, мы программы подряд пускали и несколько раз вперемешку (не могли глазам поверить), поэтому вряд ли.

Nick № 62
В Go не силён — как компилировали? Я разницы в скорости между Си и Go не получил (x86-64). (Go — 6g+6l использовал, для C — gcc 4.5 и 4.6 пробовал)
Евгений Степанищев (bolknote.ru) автор № 63
Гоу компилировался при помощи 6g и 6l, чем Миша компилировал программу на Си я не знаю, но подозреваю, что тем gcc, что стоит в Мак ОСи, тут это gcc 4.2.1 (Apple Inc. build 5666) (dot 3)
Nick № 64
Комментарий для Евгения Степанищева:

Никаких дополнительных опций оптимизации? Тогда это скорее проблема gcc 4.2. Не думаю, что дело в ОС (у меня GNU/Linux).
Denis Ibaev (dionys.myopenid.com) № 66

Комментарий для Евгения Степанищева:

Ну так за чем дело встало? Компиляторы-то для всех платформ существуют :)

Можно и не компилировать самому:

— 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, иначе для некоторых языков время выполнения превышало лимит.

Евгений Степанищев (bolknote.ru) автор № 67
Go: не запустился (undefined: append)

У них какой-то очень древний компилятор, поэтому интереса в этом мало :(

Евгений Степанищев (bolknote.ru) автор № 69
Комментарий для dionys.myopenid.com:

Тоже ведь неизвестно что там за версия. Ну и V8 лучший из открытых.
Denis Ibaev (dionys.myopenid.com) № 70

Комментарий для Евгения Степанищева:

Тоже ведь неизвестно что там за версия.

Почему неизвестно? Версия указана.

Евгений Степанищев (bolknote.ru) автор № 71
Комментарий для dionys.myopenid.com:

И правда.

На сайте SpiderMonkey версии 1.7, актуальную мне посмотреть не удалось, сайт лежит, но у меня в портах есть 1.8.5
На сайте Rhine версии 1.6.5, актуальная —1.7R3.

По меркам интерпретаторов JS — старьё. :)
proger № 79
Этот код JS можно ускорить. Опубликовать вариант не могу, так как эти примочки являются сильной стороной нового фрэймворка, который вскоре выйдет на рынок.
доброжелатель № 81

Я тут начал изучать Forth и первой программой написал тот же самый алгоритм, чтобы сравнить перфоманс.
http://hastebin.com/raw/fiqigusano
Использовал gforth и сравнивал с вашими программами на си и питоне.

$ uname -a
Linux 3.0.0-16-generic #27-Ubuntu SMP Tue Jan 24 19:14:19 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
$ gcc --version
gcc (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1
$ gcc -o prime-filter prime-filter.c
$ time ./prime-filter >/dev/null
real 0m0.759s
user 0m0.752s
sys 0m0.004s
$ python --version
Python 2.7.2+
$ time python prime-filter.py >/dev/null
real 0m19.904s
user 0m19.853s
sys 0m0.008s
$ gforth --version
gforth 0.7.0
$ time gforth prime-filter.fs >/dev/null
real 0m7.815s
user 0m7.796s
sys 0m0.000s
$ time gforth-fast prime-filter.fs >/dev/null
real 0m4.537s
user 0m4.516s
sys 0m0.008s

man gforth:

gforth-fast is the same as gforth, except that it does not support accurate backtraces for signals, and is faster by up to a factor of 2. Use it for debugged, performance-critical programs such as benchmarks.
Евгений Степанищев (bolknote.ru) автор № 83
Хорошо, что я нашёл этот пост. В случае Си «ларчик просто открывался», сейчас я уже плохо помню, но мы все примеры компилили на «Маке» и, похоже, по-умолчанию они компилировались llvm-gcc.
it-obzor.com № 84

Вообще то да, это не решето решето Эратосфена.

Вот мои результаты питона (так как я пишу на нем)

python name.py 23,33s user 0,04s system 99% cpu 23,447 total

И результаты с Гоу (так как хочу его изучать)

./name 0,83s user 0,00s system 96% cpu 0,863 total
gzim9x № 85
cорри за некропост -- не смог удержаться… perl тоже может быть достаточно быстр и короток в записи…. этот вариант быстрее предыдущего варианта на 1/3 -- из-за перехода «next LABEL» + выкинул лишние переменные + уменьшил накладные расходы на инициализацию областей видимости блоков ( вход в фигурные скобки в perl'е иногда бывает дорог;))) ).

#!/usr/bin/perl

use strict;

my @a = (2);

L: for (my $i = 3; $i
Евгений Степанищев (bolknote.ru) автор № 86
Ага, спасибо :) Когда-то я несколько лет на Перле программировал :) Но с тех пор много воды утекло. Читаю до сих пор свободно, а что-то писать уже тяжеловато :)