/update/ Статья обновлена по результатам обсуждения. Поправлен код Python (около 40% ускорения), написан код на Perl и Ruby (но меня терзают смутные сомнения, что с ruby я что-то сделал неправитьно), поправлен код на Java (на моей машине корректнее тестировать int, а не long. к тому же int в Java эквивалентен long в C++).
Вопрос производительности (скорости работы) различных языков часто всплывает в комментариях, на форумах, часто необоснованные :). Встречаются статьи, в которых авторы приводят примеры, где выигрывает реализация на том или ином языке.
После прочтения очередной статьи мне захотелось самому разобраться «здесь и сейчас». Сначала захотелось сравнить Java и C++ (не верил я, что в вычислительных тестах ява может догнать и обогнать cpp). 10 минут и простой код на C++ и яве готов: простой цикл и математические операции. После написания теста подумал и перевёл их на php и python. Позже добавился код на perl и ruby.
Итак, пару слов о тесте:
Алгоритм синтетический, долгий цикл (двухуровневый) и в нём вычисление математического выражения. Таким образом оценивается вычислительная производительность самого языка (интерпретатора или скомпилированного кода), никаких привязок к качеству реализации тех или иных библиотек, никаких внешних сервисов, никаких системозависимых операций (диск, сеть, графика).
Заранее замечу:
1) Мне нравится ява и я честно предполагал, что результаты будут лучше. Обновлено: long в 64-х битных системах работает значительно быстрее. При работе с int в 32-х битных системах Java значительно ускоряется (на моей машине быстрее, чем C++, видимо, JVM оптимизирует исполнение по умолчанию)
2) Я догадывался, что php будет медленней C++ и Java, но не думал, что он окажется быстрее Perl.
3) Предполагал, что Python будет сопоставим с PHP, но ошибся. Видимо, стандартная поставка PHP лучше оптимизирует исполнение кода.
4) Я совсем не знаком с Ruby, код взят из одного из комментариев. Причём использован код 1, так как у меня он работает быстрее чем код 2. Возможно, это также связано с тем, что у меня 32bit-система.
5) Я достаточно уважительно отношусь к различным языкам программирования, эта статья ни одним из углов не нацелена на разжигание холиваров. Каждый язык имеет свою нишу и своих поклонников.
Тесты запускались по 5 раз минимум, чтобы избежать случайных всплесков. Запускались из консоли и как «nice -n -9», то есть с максимальным на данный момент приоритетом в системе.
Чтобы не заставлять вас читать всю статью, сразу приведу краткие результаты.
Диаграмма (обновленная):
Старый вариант здесь
На диаграмме слолбец с Ruby частично прозрачен по причине того, что на моей машине скрипт Ruby исполнялся неприлично долго, в то время как в комментарии указано, что скрипт исполняется в 4 раза быстрее скрипта на Python — я в замешательстве.
Столбец с Python прозрачен, так как при включении psyco скрипт ускоряется более чем в 10 раз. Проверил на своей машине. Но это, с моей точки зрения, хак, не отражающий собственную производительность языка.
Столбец с PERL, как могут заметить старожилы, теперь идёт вровень с Python 2.6. Причиной этому послужила смена кода с C-подобного синтаксиса на использование range. Дополнительную производительность (около 12%) можно получить использовав директиву «use integer;», но это, по-моему, тоже хак.
В виде таблицы (тоже обновлённой):
Время исполнения — на P4-1.8Ггц.
Производительность — относительно производительности базового кода на C++.
Добавлен столбец с запуском Java-кода с ключём "-server". После перехода с «long» на «int» (повторюсь, int в java такой же как и long в c++ на 32bit-arch) он начал давать прирост в производительности почти вдвое.
Столбец с Ruby 1.9 на моём железе не тестировался, результат перенесён через сравнение с производительностью Python'а на той же машине.
Java, Test01.java (int в Java то же что и long в C++):
C++, Test01.cpp:
PHP, Test01.php:
Python, Test01.py (вынос кода в функцию ускоряет работу кода почти вдвое, отдельная же инициализация range() на моей машине даёт порядка 5% производительности):
Perl, Test01.pl (обновлено, с range работает на 25% быстрее против c-подобного синтаксиса for):
Ruby, Test01.rb:
Вот здесь в комментариях обсуждают решение на erlang.
Как видите, ничего сложного: два цикла и математическое выражение. Вычислительная задача в чистом виде.
мой оригинал — там старая версия статьи, а также информация об версиях использованного ПО и результаты тестов из консоли.
Ещё раз повторюсь: каждый язык имеет свою нишу, своих поклонников и свои задачи, с решением которых он справляется лучше других.
PS: а вообще, нет смысла загоняться и меряться чем бы то ни было, производительность самого языка важна для достаточно узкого круга задач, т.к. в общем случае, системы, библиотеки и прочая обвязка нынче несоизмеримо тяжелее самой вычислительной задачи.
Вопрос производительности (скорости работы) различных языков часто всплывает в комментариях, на форумах, часто необоснованные :). Встречаются статьи, в которых авторы приводят примеры, где выигрывает реализация на том или ином языке.
После прочтения очередной статьи мне захотелось самому разобраться «здесь и сейчас». Сначала захотелось сравнить Java и C++ (не верил я, что в вычислительных тестах ява может догнать и обогнать cpp). 10 минут и простой код на C++ и яве готов: простой цикл и математические операции. После написания теста подумал и перевёл их на php и python. Позже добавился код на perl и ruby.
Итак, пару слов о тесте:
Алгоритм синтетический, долгий цикл (двухуровневый) и в нём вычисление математического выражения. Таким образом оценивается вычислительная производительность самого языка (интерпретатора или скомпилированного кода), никаких привязок к качеству реализации тех или иных библиотек, никаких внешних сервисов, никаких системозависимых операций (диск, сеть, графика).
Заранее замечу:
1) Мне нравится ява и я честно предполагал, что результаты будут лучше. Обновлено: long в 64-х битных системах работает значительно быстрее. При работе с int в 32-х битных системах Java значительно ускоряется (на моей машине быстрее, чем C++, видимо, JVM оптимизирует исполнение по умолчанию)
2) Я догадывался, что php будет медленней C++ и Java, но не думал, что он окажется быстрее Perl.
3) Предполагал, что Python будет сопоставим с PHP, но ошибся. Видимо, стандартная поставка PHP лучше оптимизирует исполнение кода.
4) Я совсем не знаком с Ruby, код взят из одного из комментариев. Причём использован код 1, так как у меня он работает быстрее чем код 2. Возможно, это также связано с тем, что у меня 32bit-система.
5) Я достаточно уважительно отношусь к различным языкам программирования, эта статья ни одним из углов не нацелена на разжигание холиваров. Каждый язык имеет свою нишу и своих поклонников.
Тесты запускались по 5 раз минимум, чтобы избежать случайных всплесков. Запускались из консоли и как «nice -n -9», то есть с максимальным на данный момент приоритетом в системе.
Чтобы не заставлять вас читать всю статью, сразу приведу краткие результаты.
Диаграмма (обновленная):
Старый вариант здесь
На диаграмме слолбец с Ruby частично прозрачен по причине того, что на моей машине скрипт Ruby исполнялся неприлично долго, в то время как в комментарии указано, что скрипт исполняется в 4 раза быстрее скрипта на Python — я в замешательстве.
Столбец с Python прозрачен, так как при включении psyco скрипт ускоряется более чем в 10 раз. Проверил на своей машине. Но это, с моей точки зрения, хак, не отражающий собственную производительность языка.
Столбец с PERL, как могут заметить старожилы, теперь идёт вровень с Python 2.6. Причиной этому послужила смена кода с C-подобного синтаксиса на использование range. Дополнительную производительность (около 12%) можно получить использовав директиву «use integer;», но это, по-моему, тоже хак.
В виде таблицы (тоже обновлённой):
Язык | Java | Java -server | C++ | C++, -O2 | PHP | Python 2.6 | Python 3.1 | Perl 5.8 | Ruby 1.8 | Ruby 1.9(?) | |
Время исполнения, сек | 5,3 | 2,8 | 8,5 | 2,6 | 62 | 91 | 145 | 91 | 207 | ~30 | |
Производительность, % | 160 | 303 | 100 | 327 | 14 | 9 | 6 | 9 | 4.11 | 28 |
Время исполнения — на P4-1.8Ггц.
Производительность — относительно производительности базового кода на C++.
Добавлен столбец с запуском Java-кода с ключём "-server". После перехода с «long» на «int» (повторюсь, int в java такой же как и long в c++ на 32bit-arch) он начал давать прирост в производительности почти вдвое.
Столбец с Ruby 1.9 на моём железе не тестировался, результат перенесён через сравнение с производительностью Python'а на той же машине.
И, чтобы не быть голословным, тестовый код.
Java, Test01.java (int в Java то же что и long в C++):
package ru.dchekmarev.test.performance;
public class Test01 {
public static void main(String[] args) {
// long start = System.currentTimeMillis();
int r = 0;
for (int i = 0; i < 10000; i++) {
for (int j = 0; j < 10000; j++) {
r = (r + (i * j) % 100) % 47;
}
}
System.out.println("answer: " + r);
// закомментировано, т.к. замеры делаются из командной строки
// System.out.println("run time (millis): " + (System.currentTimeMillis() - start));
}
}
C++, Test01.cpp:
#include <iostream>
using namespace std;
int main(void) {
long r = 0;
for (int i = 0; i < 10000; i++) {
for (int j = 0; j < 10000; j++) {
r = (r + (i * j) % 100) % 47;
}
}
cout << "answer: " << r << endl;
}
PHP, Test01.php:
<?php
$r = 0;
for ($i = 0; $i < 10000; $i++) {
for ($j = 0; $j < 10000; $j++) {
$r = ($r + ($i * $j) % 100) % 47;
}
}
echo 'answer: ' . $r . "\n";
?>
Python, Test01.py (вынос кода в функцию ускоряет работу кода почти вдвое, отдельная же инициализация range() на моей машине даёт порядка 5% производительности):
def test():
r = 0
for i in range(0, 10000):
for j in range(0, 10000):
r = (r + (i * j) % 100) % 47
test()
print("answer: ", r)
Perl, Test01.pl (обновлено, с range работает на 25% быстрее против c-подобного синтаксиса for):
$r = 0;
# старый вариант, C-подобный синтаксис
# for ($i = 0; $i < 10000; $i++) {
# for ($j = 0; $j < 10000; $j++) {
for my $i (0..9999) {
for my $j (0..9999) {
$r = ($r + ($i * $j) % 100) % 47;
}
}
print "answer: $r\n";
Вот здесь приведён красивый пример на Perl, но, мне кажется, такой вариант уже слишком специфичен. Ruby, Test01.rb:
r = 0
for i in 0..10_000 do
for j in 0..10_000 do
r = ( r + ( i * j ) % 100) % 47
end
end
puts "answer: #{r}"
Вот здесь в комментариях обсуждают решение на erlang.
Как видите, ничего сложного: два цикла и математическое выражение. Вычислительная задача в чистом виде.
мой оригинал — там старая версия статьи, а также информация об версиях использованного ПО и результаты тестов из консоли.
Ещё раз повторюсь: каждый язык имеет свою нишу, своих поклонников и свои задачи, с решением которых он справляется лучше других.
PS: а вообще, нет смысла загоняться и меряться чем бы то ни было, производительность самого языка важна для достаточно узкого круга задач, т.к. в общем случае, системы, библиотеки и прочая обвязка нынче несоизмеримо тяжелее самой вычислительной задачи.