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м или в 2ух как нужно — это ЛАЖА... короче, это не правильно

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

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

я конечно понимаю, новые тренды, все такое, но в большинстве браузеров, твой блог без джса и цсса, а то что он в 1м или в 2ух как нужно — это ЛАЖА… короче, это не правильно

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

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

aktuba

Цифры удивили, если честно. Но для полной картины наверное все исходники надо выложить ;)

dinoel

Результаты несолько неожиданные:
буква «К» в слове «несолько» пропущена :)

librarian (libc6.org)

А тексты программ можешь выложить? И версии интерпретаторов. Меня тоже perl удивил, вроде как уж у кого, должно быть с производительностью ок, так это у него.

greli (greli.livejournal.com)

Интересно ещё было бы запустить на JavaScript. На маке уже вроде во всех браузерах JIT.

vitaly

Для компиляции Go использовался gccgo или 6g?

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

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

Для компиляции Go использовался gccgo или 6g?

6g.

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

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

perl 5.10 http://pastebin.com/6ejFTcrH
python 2.6.1 http://pastebin.com/v6WR4CpE

других у меня пока нет, попрошу ребят, которые писали, сюда положить

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

Комментарий для greli.livejournal.com:

Интересно ещё было бы запустить на JavaScript. На маке уже вроде во всех браузерах JIT.

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

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

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

Михаил

Ого. Вот так новости. Ну это вааааще.

Sergey Palyanov (blog.chaotics.org)

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

Исправленный скрипт отрабатывает 23 секунду, то есть быстрее чем на Python.
http://pastebin.com/TLnpZXgp

Sergey Palyanov (blog.chaotics.org)

Опечатался: Perl-скрипт отрабатывает за 21 секунду.

Александр Карпинский

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

Сергей, а вы обладатель того самого эталонного ноутбука, на котором проводились тесты?

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

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

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

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

Saper

С# бы ещё посмотреть.

Александр Карпинский

Есть целый проект исследования производительности языков. Судя по нему, Go по всем тестам оказывается медленнее Си.
http://shootout.alioth.debian.org/u32/benchmark.php?test=all%26lang=go%26lang2=gcc

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

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

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

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

Александр Карпинский

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

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

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

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

Завтра посмотрим как выполняется версия на JS под нашим эталонным Маком :) «Опера» последняя бралась? 11.50RC1?

Александр Карпинский

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

Да.

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

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

С# бы ещё посмотреть.

Ну, пустить его под Маком, кажется, нетривиальная задача. Да и эксперимент будет нечестным — для C# это чужеродная среда.

mixael

Всем привет.
Выкладываю все исходники!
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.

mixael

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

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

Спасибо, Миш!

JS добавил, несправедливость с Перлом пофиксил.

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

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

Кстати, у Володи есть версия на C++, завтра и её надо будет потестировать, но там что-то не очень впечатляющее по скорости получается, судя по всему.

aktuba

Ну раз уж пошли доработки — доработайте немного php-версию. Вынесите count из for — прирост на моем ноуте примерно 33%.
И таки да — даже в 2011 году php не может нормально обрабатывать циклы =(

aktuba

Упс, ошибка. Прирост составил примерно 66%, а не 33. Т. е. по скорости получится так же, как и питон/перл, возможно чуть быстрее.

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

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

Положите на pastebin.com ваш вариант, Миша запустит как увидит комментарий.

Сергей

А зачем PHP так замучили? Требую реабилитации!
http://pastie.textmate.org/private/eovr5vhhyynup4qabp63a

aktuba

http://pastebin.com/zHZxrw05
Не удобно с айфона набирать )
Вариант Сергея, кстати, лучше. Но не думаю, что сильно поможет, если честно.

eyeless

Какие-то странные у вас реализации. До того, чтобы перебирать только четные числа додумались, а до того, чтобы ограничить перебор делителей корнем из тестируемого числа — нет?

zitter

Хочется С++ и фортран для счастья

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

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

А зачем PHP так замучили? Требую реабилитации!

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

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

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

Какие-то странные у вас реализации. До того, чтобы перебирать только четные числа додумались, а до того, чтобы ограничить перебор делителей корнем из тестируемого числа — нет?

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

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

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

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

Хочется С++ и фортран для счастья

C++ будет, а Фортран у нас не знает никто.

mixael

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

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

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

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

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

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

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

mixael

php 21 сек

aktuba

А мой вариант замерили? Алгоритм то тот же?

aktuba

Упс, не увидел сразу. Ускорение в 2.5 раза на одном count... Пора менять php на node.js

artemp.pip.verisignlabs.com

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

со скуки (в интернете кто-то неправ :) ) померил на неэталонном 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)

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

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

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

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

Утилита time.

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

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

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

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

Vladimir Moskva (fulc.ru)

На всякий случай сюда тоже напишу, что этот алгоритм — не решето Эратосфена. В классическом решете нет деления с остатком.

Vladimir Moskva (fulc.ru)

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

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

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

whtiger

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

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

Сергей

Вот мой вариант на С++
http://pastie.textmate.org/private/xhet0zuufqo3yhfyic6ga
у меня с С разницы по скорости 0 (gcc 4.4.5)

Сергей

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

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

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

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

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

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

Vladimir Moskva (fulc.ru)

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

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

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

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

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

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

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

С++ — 0,82.  http://pastebin.com/p3c6MJp0

artemp.pip.verisignlabs.com

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

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

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

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

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

Опять же:

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

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

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

artemp.pip.verisignlabs.com

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

Хотя, если

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

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

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

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

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

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

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

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

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

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

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

По поводу разницы старта скомпилированных программ и интерпретируемых с интерпретатором.

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

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

artemp.pip.verisignlabs.com

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

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

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

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

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

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

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

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

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

Максим Зотов (maxim-zotov.livejournal.com)

А частота процессора была всего одна и та же у эталонного ноутбука?
По умолчанию система может произвольно менять частоту. Допустим, Go исполнялся на 2.5 GHz, а C — на 2.

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

Комментарий для maxim-zotov.livejournal.com:

А частота процессора была всего одна и та же у эталонного ноутбука?

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

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

Nick

В Go не силён — как компилировали? Я разницы в скорости между Си и Go не получил (x86-64). (Go — 6g+6l использовал, для C — gcc 4.5 и 4.6 пробовал)

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

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

Гоу компилировался при помощи 6g и 6l, чем Миша компилировал программу на Си я не знаю, но подозреваю, что тем gcc, что стоит в Мак ОСи, тут это gcc 4.2.1 (Apple Inc. build 5666) (dot 3)

Nick

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

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

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

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

Никаких, да.

Denis Ibaev (dionys.myopenid.com)

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

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

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

— 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)

Комментарий для dionys.myopenid.com:

Go: не запустился (undefined: append)

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

Denis Ibaev (dionys.myopenid.com)

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

Зато другие языки можно сравнить. Вон JavaScript уже не столь хорош.

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

Комментарий для dionys.myopenid.com:

Тоже ведь неизвестно что там за версия. Ну и V8 лучший из открытых.

Denis Ibaev (dionys.myopenid.com)

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

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

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

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

Комментарий для dionys.myopenid.com:

И правда.

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

По меркам интерпретаторов JS — старьё. :)

Denis Ibaev (dionys.myopenid.com)
shaggyboy

 for($j=0; $j<count($x); $j++)
стандартная ошибка, каунт пересчитывается на каждой итерации
надо писать
 for($j=0 $max = count($x),$j<$max; $j++)

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

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

Нет тут никакой ошибки.

Задачи сделать максимально быстро нет. Есть задача повторить тот же алгоритм на разных языках.

Helgus (he1gus.livejournal.com)

А вот и на Ruby
тестить желательно на 1.9.2
http://pastebin.com/xHbRKnmk

arseniy.net

Python test:
CPython — 12.11 sec
PyPy — 1.266 sec
/trollface

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

Комментарий для he1gus.livejournal.com:

А вот и на Ruby

Сейчас уже не смогу потестить, «эталонная» машина за много сотен километров.

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

/trollface

Почему?

proger

Этот код JS можно ускорить. Опубликовать вариант не могу, так как эти примочки являются сильной стороной нового фрэймворка, который вскоре выйдет на рынок.

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

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

Я несколько раз написал, что ничего ускорять не надо.

доброжелатель

Я тут начал изучать 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.

KeFA

package main
func main() {

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)

}

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

Хорошо, что я нашёл этот пост. В случае Си «ларчик просто открывался», сейчас я уже плохо помню, но мы все примеры компилили на «Маке» и, похоже, по-умолчанию они компилировались llvm-gcc.

http://it-obzor.com

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

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

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

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;

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

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

Ага, спасибо :) Когда-то я несколько лет на Перле программировал :) Но с тех пор много воды утекло. Читаю до сих пор свободно, а что-то писать уже тяжеловато :)

Популярное