Производительность C++ vs. Java vs. PHP vs. Python. Тест «в лоб»

    /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;», но это, по-моему, тоже хак.

    В виде таблицы (тоже обновлённой):
    Язык 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: а вообще, нет смысла загоняться и меряться чем бы то ни было, производительность самого языка важна для достаточно узкого круга задач, т.к. в общем случае, системы, библиотеки и прочая обвязка нынче несоизмеримо тяжелее самой вычислительной задачи.
    Метки:
    Поделиться публикацией
    Комментарии 216
    • –19
      А почему вы в одно сравнение вынесли тесты консольных приложений (c++ и java) и тесты под вэб, которые выполняются на вэб-сервере? По-моему их так сравнивать неуместно.
      • +9
        Как видно по ссылке на оригинал, php и python точно так же тестировались в консоли. Никто не заставляет использовать эти языки только для веба :) Как и никто не запрещает писать cgi на ассемблере. Как и говорил автор, у каждого языка своя ниша.
        • +4
          И еще, тот факт, что long и int в java не одно и тоже, что в c++
          100000000 операций с областями памяти в 8 и 4 байта не одно и тоже, что с 4 и 2 байта.
          • +1
            насчет области памяти в 2 байта — это очень вряд ли, отдельные переменные выравниваются по машинному слову
            кстати, если уж на то пошло, в питоне вообще разрядность числа ограничена виртуальной памятью
            • +1
              Вы оказались правы, long в Java съедал всю малину
            • +7
              «Из чего лучше пить кофе: чайник, чашка, трамвай или абрикос?»
            • +2
              При времени выполнения кода в 200 сек затраты на создание контекста несущественны.
              • НЛО прилетело и опубликовало эту надпись здесь
                • 0
                  А в некоторых местах они будут медленней из-за сборщика мусора.
              • –8
                Спасибо, все просто и наглядно
                • НЛО прилетело и опубликовало эту надпись здесь
                • +1
                  Можно было бы и С# протестить.
                  • +1
                    К сожалению, сейчас у меня нет такой возможности. Но, уже после написания статьи, пришла мысль, что действительно стоило бы тестировать бОльший набор языков и по бОльшему числу параметров (кроме циклов взять создание классов, вызовы методов, простых функций, статический, динамический контекст).
                    Думаю, в скором времени будут другие тесты — самому всё ещё любопытно.
                  • –11
                    Спасибо знал что C++ лучший :)
                    • +4
                      у каждого языка своя ниша как сказал автор. не существует лучших языков.
                      • 0
                        какая ниша у brainfuck или у HQ9+? =)
                        • +3
                          из названия первого всё ясно
                          • 0
                            HQ9++ можно слегка доработать (до HQ9++T например), и потом использовать студентами в курсах «написать задание на любом ОО-языке» в виде сдачи иходников программы main.hq9:«T» и её компилятора (а команде Т в рамках языка будет совершенно случайно реализовываться то, что требовалось по заданию)

                            соррри за бред, была такая идея сделать так в этом семестре, только заломало почему-то :)
                        • 0
                          а может ASM?
                          • +3
                            я не думаю, что асм будет сильно отличаться от c++
                            • +3
                              какой идиот вас заминусовал?
                              • НЛО прилетело и опубликовало эту надпись здесь
                                • +3
                                  Что-то писать тут мне уже страшно )))
                                  • НЛО прилетело и опубликовало эту надпись здесь
                                • 0
                                  Более того, иногда компилятор лучше «знает» как создать более оптимизированный код под конкретную систему/процессор. И хороший asm-код для одной системы может уступать С++ коду на другой. Да и вообще в таких тестах, говоря что тестируют язык, должны понимать что компилятор/транслятор и есть этот самый язык. А в асме компилятор, по большому счету это программист :)
                                  • 0
                                    На самом деле асм отрабатывает (на x86) где-то в полтора раза быстрее чем неоптимизированный C++ код и медленнее, чем оптимизированный (всё-таки gcc не зря флажки разные имеет :) )
                                    • 0
                                      Странное заявление, тот же компилятор С++ переводит все в тот же «асм» (команды проца). Потому как может быть асм быстрее асма?
                                      • +2
                                        Просто компилятор лучше оптимизирует, чем я
                                  • 0
                                    На асме выходит чуть быстрее, чем C++ без оптимизации, общий алгоритм такой (если кто-то знает как улучшить — велкам):

                                    # %ecx = r = 0
                                    xorl %ecx, %ecx
                                    movl $10000, %eax

                                    _loop1:
                                    movl $10000, %ebx

                                    _loop2:
                                    # сохранили
                                    pushl %ebx
                                    pushl %eax

                                    # eax = i * j
                                    decl %eax
                                    decl %ebx
                                    mull %ebx

                                    # edx = eax % 100
                                    xorl %edx, %edx
                                    movl $100, %ebx
                                    divl %ebx

                                    # ecx = ecx® + edx
                                    addl %edx, %ecx

                                    # ecx = ecx % 47
                                    movl %ecx, %eax
                                    xorl %edx, %edx
                                    movl $47, %ebx
                                    divl %ebx
                                    movl %edx, %ecx

                                    # восстановили регистры
                                    popl %eax
                                    popl %ebx

                                    decl %ebx
                                    jnz _loop2
                                    decl %eax
                                    jnz _loop1

                                    # здесь в %ecx имеем результат

                                    общий вид здесь: dchekmarev.ru/blog/article/1249836445
                                  • –2
                                    ок, лол.
                                  • 0
                                    а почему оптимизация использовалась только для c++, а не для всех? я не говорю о том, что какой то язык при оптимизации может обогнать другой. просто было бы очень интересно на это глянуть.
                                    • –1
                                      Просто потому, что я знал, как включить её в компляторе (gcc). Но референсной была выбрана версия без оптимизации.
                                      Кстати, не подскажете, как её включить для python/java (пока не силён в опциях)?
                                      • +10
                                        Про Python:
                                        Замените range() на xrange(),
                                        Для некоторой оптимизации можно запускать файл, как `python -O ./Test01.py` (в ключе буква, а не цифра),
                                        либо использовать сторонние библиотеки типа psyco.
                                        • 0
                                          Замена range на xrange не всегда даёт прирост производительности, кстати. Иногда бывает быстрее просто породить весь список целиком, чем «генератором» «генерить» :)
                                          • 0
                                            Попробовал сейчас range и xrange, после первого прогона разница около 20 секунд.
                                            Даже учитывая то, что кроме python'a на компьютере выполняется куча других программ, разница достаточная.
                                            • 0
                                              я таки тоже протестил и с xrange время выросло на ~10 секунд :)
                                              • 0
                                                В моем случае xrange ускоряет на 2 секунды (17 против 19 секунд).
                                                Использовать range имеет смысл обычно для небольших диапазонов.
                                          • 0
                                            Такой заменой код только замедлится:
                                            range — создает список в памяти.
                                            xrange — возвращает обьект-итератор.

                                            Использование xrange приводит к экономии памяти.

                                            Кроме того, тест выполнялся на python3, где xrange вообще отсутвует, его функции перебрал на себя просто range.
                                          • +6
                                            без замены range на xrange
                                            без psyco 36.94 сек
                                            c psyco.full() 4.38 сек

                                            с заменой range на xrange
                                            без psyco 35.44 сек
                                            c psyco.full() 4.55 сек
                                            • 0
                                              Для Java нужно как минимум запускать ява-машину с ключом -server (то есть в режиме для сервера). В нем больше ресурсов затрачивается на JIT-компиляцию при первоначальном запуске.

                                              Еще на самом деле стоит удлинить время выполнения теста, чтоб время JIT-компиляции меньше влияло на результат.
                                          • 0
                                            Все-таки, неплохо было бы увидеть в тесте Perl и Ruby.
                                            • 0
                                              Упс, Perl я как раз знаю, просто забыл :) А вот с Ruby пока несколько сложнее
                                              • +1
                                                Ruby. Можно 1.8 и 1.9
                                                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 r
                                                
                                                • 0
                                                  У меня в версии Ruby 1.8 выдаёт, гм, «плохие результаты». Почти вдвое медленней питона 2.6. Это нормально или я что-то не так делаю?
                                                  • НЛО прилетело и опубликовало эту надпись здесь
                                                  • +1
                                                    в Руби правильно так
                                                    r = 0
                                                    10000.times do |i|
                                                    	10000.times do |j|
                                                            	r = (r + (i * j) % 100) % 47
                                                        	end
                                                    end
                                                    puts "answer: #{r}"
                                                    
                                                    
                                                    • +1
                                                      ruby 1.9.1p129
                                                      real    0m13.097s
                                                      user    0m13.074s
                                                      sys     0m0.020s
                                                      


                                                      Python 2.4.3
                                                      real    0m50.666s
                                                      user    0m50.580s
                                                      sys     0m0.052s
                                                      
                                                      • +1
                                                        в ruby 1.9 прикрутили JIT
                                                        в python его роль, когда нужно, выполняет psyco
                                                        • +1
                                                          Ткните пальцем, где инфа про JIT в MRI 1.9?

                                                          Про Python зная, что JIT есть в PyPy и psyco.
                                                          Про Ruby знаю, что JIT есть в JRuby, Rubinius (типа PyPy), MacRuby, IronRuby, Ruby.NET. В случае JRuby это JVM JIT, в случае IronRuby и Ruby.NET — CLR JIT.
                                              • –1
                                                Это однопроходные тесты? Запустили-померяли и в таблицу?
                                                • 0
                                                  Нет, для надёжности запускал по 5 раз. С «nice -n -9», дабы никто не мешал. На большее не хватило терпения. Когда убедился, что числа более-менее постоянны, брал наиболее близкий к среднему результат.
                                                  • +3
                                                    Надо брать минимум, потому что никакие посторонние процессы не могут заставить процесс выполняться быстрее, чем он может, только медленнее :). Об этом писал Крис Касперски
                                                • 0
                                                  почему в коде на Java делается операция вывода на экран, а после этого только замеряется время
                                                  System.out.println(«answer: » + r);
                                                  System.out.println(«run time (millis): » + (System.currentTimeMillis() — start));
                                                  • –1
                                                    это вообще может повлиять?
                                                    • 0
                                                      проверил, разница 1 мс
                                                      • +1
                                                        в смысле 0.1 сек
                                                      • +1
                                                        да! у меня разница в 0.2 сек, а если расчет делать как делается для C++ то получается разница в секунду. это на C2D 1.86, т.е. у автора она будет еще больше.
                                                    • 0
                                                      Сравнил c++, mono, java на:

                                                      • 0
                                                        model name: Intel® Core(TM)2 Quad CPU Q6600 @ 2.40GHz

                                                        c++ без оптимизации:

                                                        answer: 39
                                                        real 0m0.872s
                                                        user 0m0.840s
                                                        sys 0m0.008s

                                                        С оптимизацией -О2

                                                        answer: 39
                                                        real 0m2.682s
                                                        user 0m2.672s
                                                        sys 0m0.000s

                                                        mono:
                                                        answer: 39
                                                        run time (millis): 3731.452

                                                        java:
                                                        #time java ru.dchekmarev.test.performance.Test01
                                                        answer: 39
                                                        run time (millis): 877

                                                        real 0m0.992s
                                                        user 0m0.932s
                                                        sys 0m0.012s

                                                        Так-что никакиь 16 секунд нет ;)
                                                        • НЛО прилетело и опубликовало эту надпись здесь
                                                          • –1
                                                            Эээ… Как Вы это сделали?
                                                            Попробовал на одном из серверов:

                                                            $ cat /proc/cpuinfo |fgrep 'model name'
                                                            model name: Dual-Core AMD Opteron(tm) Processor 2218
                                                            model name: Dual-Core AMD Opteron(tm) Processor 2218
                                                            model name: Dual-Core AMD Opteron(tm) Processor 2218
                                                            model name: Dual-Core AMD Opteron(tm) Processor 2218

                                                            # time nice -n -9 java ru.dchekmarev.test.performance.Test01
                                                            answer: 39
                                                            run time (millis): 4653

                                                            real 0m6.540s
                                                            user 0m4.697s
                                                            sys 0m0.017s
                                                            • +1
                                                              Версия явы:
                                                              java version «1.6.0_14»
                                                              Java(TM) SE Runtime Environment (build 1.6.0_14-b08)
                                                              Java HotSpot(TM) 64-Bit Server VM (build 14.0-b16, mixed mode)

                                                              Может стоит попробовать запустить яву с ключом -server?
                                                              • –1
                                                                "-server" прироста не даёт, как дома, так и на машине, что комментом выше. Поэтому сразу без него и пускал. Пока что не знаю почему.
                                                                Кажется, я понял, почему у меня так тормозит: 32-х битная версия. Сейчас попробую найти среди контактов кого-нибудь с 64-х битной и потестить
                                                                • 0
                                                                  Насколько я знаю, -server влияет только на gc. Маловероятно, что это что-то поменяет во времени выполнения данного алгоритма.
                                                                  • 0
                                                                    -server еще влияет на JIT. Но для простого алгоритма вполне вероятно может не быть разницы.
                                                                    • 0
                                                                      На самом деле запускать надо только с ключем -server. в 1.6 java на сколько я знаю по умолчанию запускается с ключем -server.
                                                                      Разница в том, что в клиенской части, выделяется минимальная память, и минильный кэш, и по мере необходимости ресурсы добавляются, что весьма тормозит выполнение кода. В серверной части такого нету.

                                                                      P.S. правильней все-таки считать время выполнение не по запуску приложения, а внутри приложения(потому что язык java все-таки язык интерпретатор). к примеру:
                                                                      (количество итераций можно задавать через параметр при запуске)
                                                                      package com;

                                                                      public class Test01 {
                                                                      public static void main(String[] args) {
                                                                      final int countIteration;
                                                                      long totalWorkingTime = 0;
                                                                      if (args != null && args.length > 0) {
                                                                      countIteration = Integer.parseInt(args[0]);
                                                                      } else {
                                                                      countIteration = 10;
                                                                      }

                                                                      for (int k = 0; k < countIteration; k++) {
                                                                      final 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;
                                                                      }
                                                                      }
                                                                      final long iterationTime = System.currentTimeMillis() — start;
                                                                      totalWorkingTime += iterationTime;
                                                                      System.out.println(«time:» + iterationTime + "\nanswer: " + r);
                                                                      }
                                                                      System.out.println(«Total average time: » + (totalWorkingTime / countIteration));
                                                                      }
                                                                      }
                                                                • НЛО прилетело и опубликовало эту надпись здесь
                                                          • –2
                                                            На моем C2D 1.86 тест на java выполняется за 8.1 сек, т.е. быстрее чем на P4-1.8.
                                                            • +8
                                                              По уму, код на питоне должне быть такой:

                                                              r = 0
                                                              i1 = range(0, 10000)

                                                              for i in i1:
                                                                for j in i2:
                                                                  r = ...
                                                              
                                                              print r
                                                              


                                                              зачем 10000 раз генерить второй список (range)?

                                                              Время выполнения упало с 1.82 с при вашем варианте к 1.16 с при моём.
                                                              • +3
                                                                psyco даёт еще чуть-чуть выигрыша, но я не думаю, что это честно. в пыхе же (явно) не используются никакие «ускорители».
                                                                • +2
                                                                  psyco даст не совсем даже не «чуть-чуть выигрыша» на этом примере

                                                                  без него:
                                                                  real 0m37.201s
                                                                  user 0m36.144s
                                                                  sys 0m0.142s

                                                                  с psyco:
                                                                  real 0m3.104s
                                                                  user 0m2.895s
                                                                  sys 0m0.036s

                                                                  Ускорение в 12+ раз. Если проецировать на результаты питона из статьи, с psyco должно быть быстрее, чем java, и немного недотягивать до c++.
                                                                  • –1
                                                                    У меня совсем другие цифры. Всё что пишется про цифры и рост/падение производительности сильно зависит от окружения и способа тестирования. Имхо.
                                                                    • +2
                                                                      Не вижу не одной причины, по какой psyco не ускорит этот код раз в 10 в любом окружении. Как раз для него задачка)

                                                                      def test():
                                                                          r = 0
                                                                          rng = range(0, 10000)
                                                                          for i in rng:
                                                                              for j in rng:
                                                                                  r = (r + (i * j) % 100) % 47
                                                                          print("answer: ", r)
                                                                      
                                                                      if __name__ == '__main__':
                                                                          import psyco
                                                                          psyco.bind(test)
                                                                          test()
                                                                      
                                                                      
                                                                      • +3
                                                                        Я просто не умею готовить psyco :) Прошу прощения, в таком варианте действительно время с 1m12s упало до 0m6s :-D

                                                                        Я-то тупо psyco.full() запускал, как quickstart guide написано :).
                                                                        • +2
                                                                          psyco.full() тоже работает, секрет в том, что код вынесен в функцию.
                                                                        • +2
                                                                          Спасибо, действительно в 10 раз. Получается psyco можно применять только в функциям, а к коду на верхнем уровне он бессилен?
                                                                          • +1
                                                                            Видимо, так. Могу только предположить, что при работе psyco.full() psyco требуется получить код, который компилировать, для этого он ставит хук на вызовы функций и при обращении компилирует их по возможности.
                                                                            • +2
                                                                              нашел в документации: Psyco only compiles functions. It will not accelerate any code that runs outside any function, like…

                                                                              psyco.sourceforge.net/psycoguide/unsupported.html
                                                                        • 0
                                                                          Можете привести весь код? У меня тоже не дало результата.
                                                                        • 0
                                                                          И да, это, конечно же, не честно. Но раз уж и так сравнение кода интерпретируемого с кодом компилированным, почему бы JIT не использовать.
                                                                          • 0
                                                                            Я, кстати, не разбирался особо с psyco никогда. Он не средствами языка это делает, случаем? :)
                                                                            • +1
                                                                              там заброшенная и неподдерживаемая черная магия)
                                                                              Силы автора направлены на PyPy, интерпретатор питона с JIT, реализованный на питоне (вот тут все делается средствами языка), который должен все ускорить до небывалых высот.
                                                                        • 0
                                                                          Мой опыт с Python — чтение «start with python» :) Сейчас пропишу в статье вашу правку, спасибо
                                                                          • +2
                                                                            Испробовал python 3, unladen-swallow все в llvm, psyco:

                                                                            Python 3 почему то главный тормоз:
                                                                            • +2
                                                                              Python 3:
                                                                              mkrivushin@root:~/w/python$ python3 test_3.py
                                                                              70.3983209133
                                                                              answer:  39
                                                                              

                                                                              Unladen Swallow:
                                                                              mkrivushin@root:~/w/python/unladen-swallow$ ./python -O ../test.py
                                                                              44.4158890247
                                                                              ('answer: ', 39)
                                                                              mkrivushin@root:~/w/python/unladen-swallow$ ./python -O -j always ../test.py
                                                                              34.8978021145
                                                                              ('answer: ', 39)
                                                                              

                                                                              Psyco:
                                                                              mkrivushin@root:~/w/python$ python test.py
                                                                              6.42809700966
                                                                              ('answer: ', 39)
                                                                              

                                                                              Жалко, что пока unladen не так крут.
                                                                            • 0
                                                                              А если вместо range использовать xrange что-то изменится?
                                                                              • 0
                                                                                Выше уже обсудили, но во мнениях так и не сошлись.
                                                                                • 0
                                                                                  надо действительно в данном случае не «for x in range» а «variab = range(1,1000); for x in variab»
                                                                            • 0
                                                                              никаких привязок к качеству реализации тех или иных библиотек, никаких внешних сервисов, никаких системозависимых операций

                                                                              А как насчет вывода на консоль? Все-таки операция я потоками (streams)…
                                                                              • 0
                                                                                Пардон, с потоками
                                                                              • +1
                                                                                Интересно посмотреть как в эту картину впишется код на пыхе с использованием range в цикле.
                                                                                • +3
                                                                                  вы ещё к java добавте пару ключиков и прогоните этот тест раз 100 что бы java машина прогреласть

                                                                                  -server
                                                                                  -agressiveots
                                                                                  и тд
                                                                                  • 0
                                                                                    ОС: winxp sp3.
                                                                                    Язык: jscript.
                                                                                    Процессор: Intel Core 2 Quad CPU Q6600 2.40GHz.
                                                                                    Память: DDR3 4096 MBytes.
                                                                                    Проходов: 50.
                                                                                    Среднее время: 33634 мс.
                                                                                    Разброс: 33531 мс — 33703 мс.

                                                                                    • 0
                                                                                      И какая тут платформа, т.е. браузер ну или точнее JS движёк?
                                                                                      • 0
                                                                                        windows script host.

                                                                                        P.S.: Накладные расходы на каждый тест в сумме менее 0.1 мс, точнее не получается.
                                                                                      • +1
                                                                                        Эти пипиркомерки так же бессмысленны, как и увлекательны :)
                                                                                        Вот результат для Javascript, Google v8.

                                                                                        1 var r = 0;
                                                                                        2 for(var i=0; i<10000; i++) {
                                                                                        3 for(var j=0; j<10000; j++) {
                                                                                        4 r = (r + (i * j) % 100) % 47;
                                                                                        5 }
                                                                                        6 }
                                                                                        7 print(r+"\n");

                                                                                        ~/tmp$ time ~/Projects/V8/v8/shell ./dzmitryc.js
                                                                                        39

                                                                                        real 0m3.243s
                                                                                        user 0m3.194s
                                                                                        sys 0m0.022s
                                                                                      • +6
                                                                                        Как сказал мой очень хороший друг — сравнивать так данные языки на равных несерьезно, т.к. одно написаны на другом.
                                                                                        Заодно он подкинул мне ссылку на более подробное сравнение языков, которой я бы, в свою очередь, хотел поделиться с Вами — http://shootout.alioth.debian.org/
                                                                                        • –7
                                                                                          О друге скажу следующее — человек очень серьезно занимается программированием. В данный момент работает над своей операционной системой и языком программирования. Не планирует сделать, а уже написал рабочие прототипы, которые развивает дальше.
                                                                                          • 0
                                                                                            Расскажите еще про вашего друга.
                                                                                          • –1
                                                                                            Я и написал, что это синтетический тест, который показывает просто производительность :)
                                                                                            А за ссылку спасибо, да, там куда серьёзнее
                                                                                            • 0
                                                                                              А в чём проблема такого сравнения? Сейчас границы «специфичности» слегка стираются, и каждый из приведённых языков вполне прокатывает в качестве языка «общего назначения». Стало быть, двойной цикл + вычисление математического выражения не выглядит ни для одного из языков совсем уж чужеродным.

                                                                                              Ну да, я понимаю, что на одних пишут веб-скрипты, на других игры, на третьих апплеты и т.д. Тут понятно, на С++ апплет не напишешь. Но если язык используется именно как general purpose language, почему бы не устроить простой тест производительности?
                                                                                              • 0
                                                                                                Если быть уж совсем честным — а какой Вы результат ожидаете от такого сравнения? Что он сподвигнет изучать тот или иной язык? У каждого языка, все-таки, своя специфика применения. Опять же, в большинстве своем интерпретируемый язык будет уступать. Опять же, какая модель вычисления используемся, какова реализация? Большинство интерпретируемых языков используют стековую ВМ, которая по производительности почти на порядок уступает регистровой.
                                                                                                Да, мне было интересно увидеть эти цифры, но это всё настолько относительно…

                                                                                                • +1
                                                                                                  Да мне многого и не надо — предположим, ко мне приходит приятель и говорит: я запрограммировал расчёт такой-то математической модели, она у меня работает на языке Х и считает примерно сутки задачу среднего размера.

                                                                                                  Тогда я смогу сказать что-то вроде: перейдя на язык Y, ты смог бы посчитать задачу среднего размера за 10 часов. Вот и всё.
                                                                                                  • 0
                                                                                                    Тут я — согласен. Все равно, не стоит забывать, что изучение языка — дело ни одной минуты. У каждого языка есть свои особенности, тонкости и «узкие» места.
                                                                                            • 0
                                                                                              model name: Intel® Core(TM)2 CPU 6300 @ 1.86GHz
                                                                                              gcc 4.3
                                                                                              real 0m1.586s
                                                                                              user 0m1.500s
                                                                                              sys 0m0.024s

                                                                                              gcj 4.3
                                                                                              real 0m7.114s
                                                                                              user 0m6.952s
                                                                                              sys 0m0.028s

                                                                                              java 1.6.0_14
                                                                                              real 0m7.500s
                                                                                              user 0m7.264s
                                                                                              sys 0m0.012s

                                                                                              java 1.6.0_14 server
                                                                                              real 0m0.116s
                                                                                              user 0m0.060s
                                                                                              sys 0m0.016s

                                                                                              python2.6
                                                                                              real 0m57.403s
                                                                                              user 0m55.363s
                                                                                              sys 0m0.272s
                                                                                              • +1
                                                                                                Я не удивлен тем что C++ сделал Java, на то он и сложней чтобы быстрей работал.

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

                                                                                                Тем не менее, здесь результаты сравнения PHP и Python другие

                                                                                                shootout.alioth.debian.org/debian/benchmark.php?test=all&lang=php&lang2=python&box=1
                                                                                                • 0
                                                                                                  По вашей ссылке профессионалы в своих языках оптимизируют алгоритмы от и до, стараясь выжать по максимуму. Автор же этой заметки вообще в питоне не в зуб ногой, чего вы хотели?: )
                                                                                                  • 0
                                                                                                    > По вашей ссылке профессионалы в своих языках оптимизируют алгоритмы от и до, стараясь выжать по максимуму.

                                                                                                    Что-то подсказывает мне, что мы в этом посте тоже к этому придём коллективными усилиями :)
                                                                                                • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                  • 0
                                                                                                    The «C is Efficient» Language Fallacy переходим на OCaml? :)
                                                                                                    • +1
                                                                                                      кстати насчет ocaml:

                                                                                                      let r = ref 0;;

                                                                                                      let tstfunc x =
                                                                                                      for i = 1 to x do
                                                                                                      for j = 1 to x do
                                                                                                      r := (!r + (i * j) mod 100) mod 47;
                                                                                                      done;
                                                                                                      done;;
                                                                                                      tstfunc 10000;;
                                                                                                      Printf.printf «Result %d\n» !r;;

                                                                                                      и дальше
                                                                                                      $ ocamlopt speedtest.ml -o sptest
                                                                                                      $ time ./sptest
                                                                                                      Result 39

                                                                                                      real 0m6.364s
                                                                                                      user 0m6.136s
                                                                                                      sys 0m0.044s

                                                                                                      6 секунд на amd 4000+
                                                                                                      • +1
                                                                                                        на той же машине лисп cmucl
                                                                                                        (defun tst () (let (( r 0)) (dotimes (i 10000) (dotimes (j 10000) (setf r (mod (+ r (mod (* i j) 100)) 47) ) )) r))

                                                                                                        * (compile-file «test.lisp»)
                                                                                                        * (load «test»)
                                                                                                        ; Loading #p"/home/w/sandbox/test.x86f".
                                                                                                        T
                                                                                                        * (time (tst))
                                                                                                        ; Compiling LAMBDA NIL:
                                                                                                        ; Compiling Top-Level Form:

                                                                                                        ; Evaluation took:
                                                                                                        ; 10.62 seconds of real time
                                                                                                        ; 10.296644 seconds of user run time
                                                                                                        ; 0.032002 seconds of system run time
                                                                                                        ; 20,399,873,134 CPU cycles
                                                                                                        ; 0 page faults and
                                                                                                        ; 0 bytes consed.
                                                                                                        ;
                                                                                                        39

                                                                                                        То есть 10 сек
                                                                                                        • +1
                                                                                                          то же на haskell

                                                                                                          module Main where

                                                                                                          loop1 :: Int -> Int -> Int
                                                                                                          loop1 0 x = x
                                                                                                          loop1 n x = loop1 (n-1) (loop2 10000 x n)
                                                                                                          loop2 :: Int -> Int -> Int -> Int
                                                                                                          loop2 0 r _ = r
                                                                                                          loop2 j r i = loop2 (j-1) ((r + ( (i * j) `rem` 100)) `rem` 47) i

                                                                                                          main = do
                                                                                                          putStr «Result „
                                                                                                          print (loop1 10000 0)

                                                                                                          $ghc -O test.hs -o tesths
                                                                                                          $time ./tesths

                                                                                                          Result 39

                                                                                                          real 0m7.442s
                                                                                                          user 0m7.316s
                                                                                                          sys 0m0.028s

                                                                                                          7 c хвостиком (примерно полвосьмого) секунд

                                                                                                          • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                            • +1
                                                                                                              на эрланге пробовали ниже по обсуждению. вроде как не быстрее получается.
                                                                                                              • 0
                                                                                                                Да тут совсем не хаскелльный код, уж очень императивный. Даже смотриться уродливо (автор ни при чем). Имхо, тут как раз можно попробовать реализовать нормальными средствами, не переписывая алгоритм один-в-один — уж слишком хаскеллю это не идёт.
                                                                                                                • 0
                                                                                                                  module Main where

                                                                                                                  myfunc :: [Int] -> Int
                                                                                                                  myfunc r = foldl (\ r1 i -> foldl (\r2 j -> (r2 + (i*j) `rem` 100 ) `rem` 47) r1 r) 0 r

                                                                                                                  main = do

                                                                                                                  putStr «Result „
                                                                                                                  print (myfunc [0..10000])

                                                                                                                  time ./test1
                                                                                                                  Result 39

                                                                                                                  real 0m7.503s
                                                                                                                  user 0m7.216s
                                                                                                                  sys 0m0.032s

                                                                                                          • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                            • +1
                                                                                                              1) Скорее наоборот. С С++ мегаофигены пока не надо следить за памятью. Иначе рискуешь воткнуться в sigsegv.
                                                                                                              2) ocaml и erlang очень разные языки, «окамли и эрланги» — непоятно по какому признаку вы их обьединили. По наличию gc? так в python и java он тоже есть. По «функциональности» языка? так ocaml позволяет писать не функционально и приведенный пример как раз написан императивно… Поясните пожалуйста вашу мысль.
                                                                                                              • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                                • +2
                                                                                                                  Valgrind хорош, спору нет, но он не панацея. Нужно иметь полный code coverage при тестировании, чтобы его вывод имел смысл. Если ваши тесты не покрывают всего кода, (там к примеру обработки ошибок или редко встречающиеся условия), то valgrind будет просто не в курсе о том, что там может быть что-то с памятью.
                                                                                                                  То есть, как писал Дейкстра " Тестирование может доказать наличие ошибок, но никогда не докажет их отсутствие". Поэтому образно говоря в языках с встроенным управлением памяти надо постараться, чтобы слохопотать NullPointer, а в C надо очень стараться чтобы не схлопотать.
                                                                                                                  • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                        • +5
                                                                                                          В Питоне надо вставить весь код в функцию. В вашем варианте переменные записываются в массив globals(), что сильно влияет на результат. После таких изменений, код начал работать более, чем в полтора раза быстрее. Ну и range надо заменить на xrange, который и следует использовать в таких циклах. С Psyco, как описано выше в комментах, код будет работать еще быстрее.

                                                                                                          def main():
                                                                                                              r = 0
                                                                                                              for i in xrange(0, 10000):
                                                                                                                  for j in xrange(0, 10000):
                                                                                                                      r = (r + (i * j) % 100) % 47
                                                                                                          
                                                                                                              print("answer: ", r)
                                                                                                          
                                                                                                          main()
                                                                                                          
                                                                                                          • +3
                                                                                                            Кстати, код достаточно сильно не эквивалентен.
                                                                                                            Например, время старта VM у java не учитывается, а у php/python — идёт в плюс.
                                                                                                            • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                            • 0
                                                                                                              Интереса ради — C#:

                                                                                                              int r = 0;
                                                                                                              DateTime before = DateTime.Now;
                                                                                                              for (int i = 0; i < 10000; i++)
                                                                                                              {
                                                                                                                 for (int j = 0; j < 10000; j++)
                                                                                                                 {
                                                                                                                    r = (r + (i * j) % 100) % 47;
                                                                                                                 }
                                                                                                              }
                                                                                                              DateTime after = DateTime.Now;
                                                                                                              Console.WriteLine(after.Second * 1000 + after.Millisecond -
                                                                                                                                            before.Second * 1000 - before.Millisecond);
                                                                                                              

                                                                                                              выполняется в среднем 3620 мс (Pen D 3200)
                                                                                                              Если для r int заменить на long, время возрастает примерно в 1,7 раз
                                                                                                              • 0
                                                                                                                Сделал аналогичный замер, Dual-Core -1.46 — 3450мс
                                                                                                                • 0
                                                                                                                  Кстати, когда я меняю на Long время уменьшается на 100мс
                                                                                                                  • 0
                                                                                                                    вы под x64, наверное
                                                                                                                    • 0
                                                                                                                      Нет, чистые x32 =)
                                                                                                                      • 0
                                                                                                                        1394 мс — C2D T8100 2.1GHz при сборке debug, 1239 сборка releaze в MSVS'08
                                                                                                                  • 0

                                                                                                                    странно но у меня ваш код другие цифры показал
                                                                                                                    • 0
                                                                                                                      1) x64
                                                                                                                      2) архитектура Core всяко лучше
                                                                                                                    • +2
                                                                                                                      Немного оффтоп: для измерения времени выполнения лучше использовать System.Diagnostics.Stopwatch, т.к. DateTime.Now берется из установок ОС, а Stopwatch замеряет время выполнения конкретного потока.
                                                                                                                      Хотя не думаю, что в данном случае это сильно повлияло на результат.
                                                                                                                      • 0
                                                                                                                        спасибо, не знал :)
                                                                                                                      • 0
                                                                                                                        Используйте только Stopwatch для замеров производительности. с DateTime время может быть какое угодно.
                                                                                                                      • 0
                                                                                                                        Графики лучше бы обновить после корректировок — не все ведь пост до конца читают.
                                                                                                                        • 0
                                                                                                                          • 0
                                                                                                                            Эээ, а почему бы не считать разницу в тиках от начала анализируемого кода, до его конца во всех языках, а не только в java?
                                                                                                                            • –1
                                                                                                                              На самом деле и для явы результат брался из консольной «time». Время запуска JVM большой роли при тесте не играло (было в пределах 5%)
                                                                                                                              • 0
                                                                                                                                Кстати в Python3.0 код

                                                                                                                                from time import clock

                                                                                                                                clock()
                                                                                                                                r = 0.0
                                                                                                                                i = 0.0
                                                                                                                                while i < 10000.0:
                                                                                                                                j = 0.0
                                                                                                                                while j < 1000.0: # !!!
                                                                                                                                r = (r + (i * j) % 100.0) % 47.0
                                                                                                                                j += 1.0
                                                                                                                                i += 1.0
                                                                                                                                print("answer: ", r, clock())
                                                                                                                                exit()

                                                                                                                                Выдаёт 10.19, ну а с j<10000 в 10 раз больше)

                                                                                                                                Если использовать int вместо float результат ухудшается примерно на 14%.
                                                                                                                                Дело в том, что в Python целые числа хранятся специальным образом, позволяя производит вычисления с оооочень большими значениями (a = 1024**1024)
                                                                                                                                • 0
                                                                                                                                  Да, простите Dual Core 1.7 GHz
                                                                                                                            • +5
                                                                                                                              >>answer: 39</>
                                                                                                                              соппсно, тест изначально составлен неверно — нужно, чтобы получалось 42
                                                                                                                              • +1
                                                                                                                                -module(test).
                                                                                                                                -export([start/0]).
                                                                                                                                start() -> lists:foldl(fun(I, R) -> lists:foldl(fun(J, R2) -> (R2 + (I * J) rem 100) rem 47 end, R, lists:seq(0, 10000)) end, 0, lists:seq(0, 10000)).

                                                                                                                                Eshell V5.7.2 (abort with ^G)
                                                                                                                                1> c(test).
                                                                                                                                {ok,test}
                                                                                                                                2> timer:tc(test, start, []).
                                                                                                                                {31674407,39}

                                                                                                                                31сек
                                                                                                                                • +1
                                                                                                                                  erlang ;)
                                                                                                                                  • +1
                                                                                                                                    а почему не c(test,[native])?
                                                                                                                                    • +1
                                                                                                                                      -module(test).
                                                                                                                                      -export([start/0]).
                                                                                                                                      start() ->
                                                                                                                                      Seq = lists:seq(0, 10000),
                                                                                                                                      lists:foldl(fun(I, R) -> lists:foldl(fun(J, R2) -> (R2 + (I * J) rem 100) rem 47 end, R, Seq) end, 0, Seq).

                                                                                                                                      Eshell V5.7.2 (abort with ^G)
                                                                                                                                      1> c(test, [native, {hipe, o3}]).
                                                                                                                                      {ok,test}
                                                                                                                                      2> timer:tc(test, start, []).
                                                                                                                                      {27637857,39}
                                                                                                                                      3> c(test).
                                                                                                                                      {ok,test}
                                                                                                                                      4> timer:tc(test, start, []).
                                                                                                                                      {24428678,39}

                                                                                                                                      p.s. AMD Athlon(tm) X2 Dual Core Processor BE-2300
                                                                                                                                      • +3
                                                                                                                                        делаем так:

                                                                                                                                        -module(test).
                                                                                                                                        -export([start/0,run/0]).
                                                                                                                                        start() ->
                                                                                                                                        Seq = lists:seq(0, 10000),
                                                                                                                                        lists:foldl(fun(I, R) -> lists:foldl(fun(J, R2) -> (R2 + (I * J) rem 100) rem 47 end, R, Seq) end, 0, Seq).

                                                                                                                                        run() ->
                                                                                                                                        loop1(10000,0).
                                                                                                                                        loop1(0,X) -> X;
                                                                                                                                        loop1(N,X) ->
                                                                                                                                        X1 = loop2(10000,X,N),
                                                                                                                                        loop1(N-1,X1).

                                                                                                                                        loop2(0,X,_) ->X;
                                                                                                                                        loop2(J,R2,I) ->
                                                                                                                                        R = (R2 + (I * J) rem 100) rem 47,
                                                                                                                                        loop2(J-1,R,I).

                                                                                                                                        3> c(test,[native]).
                                                                                                                                        {ok,test}
                                                                                                                                        5> timer:tc(test,start,[]).
                                                                                                                                        {28965824,39}
                                                                                                                                        6> timer:tc(test,run,[]).
                                                                                                                                        {7921692,39}
                                                                                                                                        7>

                                                                                                                                        То есть вашим вариантом на моей машине — 28 сек, переписаным — 8 сек.
                                                                                                                                        • 0
                                                                                                                                          Ну тогда такой вариант :)

                                                                                                                                          run2() -> dotimes(10000, fun(I, R) -> dotimes(10000, fun(J, R2) -> (R2 + (I * J) rem 100) rem 47 end, R) end, 0).
                                                                                                                                          dotimes(0, _, Acc) -> Acc;
                                                                                                                                          dotimes(T, F, Acc) -> dotimes(T-1, F, F(T, Acc)).

                                                                                                                                          1> c(test, [native]).
                                                                                                                                          {ok,test}
                                                                                                                                          2> timer:tc(test, start, []).
                                                                                                                                          {22927752,39}
                                                                                                                                          3> timer:tc(test, run, []).
                                                                                                                                          {10201462,39}
                                                                                                                                          4> timer:tc(test, run2, []).
                                                                                                                                          {11048724,39}

                                                                                                                                          А какая версия erlang'а у вас? У меня такие результаты на erlang R13b.
                                                                                                                                          • +1
                                                                                                                                            А я тестировал на R12B5.

                                                                                                                                            Попробовал на R13B1 —
                                                                                                                                            6> timer:tc(test,start,[]).
                                                                                                                                            {19239320,39}
                                                                                                                                            7> timer:tc(test,run,[]).
                                                                                                                                            {7114840,39}
                                                                                                                                            8> timer:tc(test,run2,[]).
                                                                                                                                            {8048659,39}

                                                                                                                                            На R12B5 — 2> timer:tc(test,start,[]).
                                                                                                                                            {28226647,39}
                                                                                                                                            3> timer:tc(test,run,[]).
                                                                                                                                            {7789521,39}
                                                                                                                                            4> timer:tc(test,run2,[]).
                                                                                                                                            {8189215,39}

                                                                                                                                            Другими словами, Ваш первый вариант при переходе с R12 на R13 ускорился почти на треть — с 28 сек до 19 сек. Однако…
                                                                                                                                            А рекзультаты на функциях улучшились чуть-чуть с 7.7 и 8.1 до 7.1 и 8.0 сек…

                                                                                                                                            • +1
                                                                                                                                              Посмотрел, почему run2 получился немного медленнее чем run (хотя по смыслу это вроде то же самое).

                                                                                                                                              После дизассемблирования beam файла оказалось, что loop1 и loop2 адресуются статически, типа
                                                                                                                                              {move,{integer,10000},{x,0}}.
                                                                                                                                              {move,{x,2},{y,0}}.
                                                                                                                                              {call,3,{test,loop2,3}}. < == Вот оно
                                                                                                                                              {gc_bif,'-',{f,0},1,[{y,0},{integer,1}],{x,2}}.
                                                                                                                                              {move,{x,0},{x,1}}.
                                                                                                                                              {move,{x,2},{x,0}}.
                                                                                                                                              {call_last,2,{test,loop1,2},1}.

                                                                                                                                              А в dotimes вызывается преданная ей функция, которая в свою очередь создает переменную-функцию.
                                                                                                                                              Типа в dotimes:
                                                                                                                                              {function,dotimes,3,14}.
                                                                                                                                              {label,13}.
                                                                                                                                              {func_info,{atom,test},{atom,dotimes},3}.
                                                                                                                                              {label,14}.
                                                                                                                                              {test,is_eq_exact,{f,15},[{x,0},{integer,0}]}.
                                                                                                                                              {move,{x,2},{x,0}}.
                                                                                                                                              return.
                                                                                                                                              {label,15}.
                                                                                                                                              {allocate_zero,2,3}.
                                                                                                                                              {gc_bif,'-',{f,0},3,[{x,0},{integer,1}],{y,1}}.
                                                                                                                                              {move,{x,2},{x,4}}.
                                                                                                                                              {move,{x,1},{x,2}}.
                                                                                                                                              {move,{x,4},{x,1}}.
                                                                                                                                              {move,{x,2},{y,0}}.
                                                                                                                                              {call_fun,2}. < == Вот вызов
                                                                                                                                              {move,{y,0},{x,1}}.
                                                                                                                                              {move,{x,0},{x,2}}.
                                                                                                                                              {move,{y,1},{x,0}}.
                                                                                                                                              {call_last,3,{test,dotimes,3},2}.

                                                                                                                                              А это функция которая вызывается:

                                                                                                                                              {function,'-run2/0-fun-1-',2,21}.

                                                                                                                                              {make_fun2,{test,'-run2/0-fun-0-',3},2,29791076,1}.


                                                                                                                                              То есть простыми словами — решение с dotimes создает дополнительно 10000 переменных типа функция, которые потом собираются garbage коллектором.

                                                                                                                                      • 0
                                                                                                                                        Erlang плохо справляется с математикой, он не для этого предназначен. Так что результат неудивителен.
                                                                                                                                      • –1
                                                                                                                                        Советую также опробовать вот эту реализацию питона:
                                                                                                                                        code.google.com/p/unladen-swallow/
                                                                                                                                        • –1
                                                                                                                                          Я ведь не использовал Intel C++ или Java RTS ;) Вообще, изначально я планировал «в лоб» перевести цикл с C++ на доступные мне языки и сравнить
                                                                                                                                          • 0
                                                                                                                                            Опробовал, коммент выше.
                                                                                                                                          • 0
                                                                                                                                            ебтыть, shootout.alioth.debian.org/ же есть!
                                                                                                                                            • +2
                                                                                                                                              $r = 0;
                                                                                                                                              for my $i (0..9999) {
                                                                                                                                                for my $j (0..9999) {
                                                                                                                                              $r = ($r + ($i * $j) % 100) % 47;
                                                                                                                                                }
                                                                                                                                              }
                                                                                                                                              print "answer: $r\n";


                                                                                                                                              На языке Perl скорость увеличивается на 30%, предлагаю поправить скрипт для чистоты экперимента.
                                                                                                                                              Также непонятно почему выбрана не самая последняя версия Perl 5.10.0
                                                                                                                                              У меня скрипт выполнялся 27 секунд
                                                                                                                                              • 0
                                                                                                                                                Действительно. Почему на Python автор вынес инициализацию данных в range, а на Perl — нет? В таком случае на каждой итерации не происходит проверки условия.
                                                                                                                                                У меня perl5.10.0 выполнял скрипт в среднем 60 секунд из 5 запусков. Машина:
                                                                                                                                                $ uname -a; grep -i mhz /proc/cpuinfo 
                                                                                                                                                Linux desktop 2.6.27.19-3.2-default #1 SMP 2009-02-25 15:40:44 +0100 i686 i686 i386 GNU/Linux
                                                                                                                                                cpu MHz		: 3215.441
                                                                                                                                                cpu MHz		: 3215.441
                                                                                                                                                

                                                                                                                                                • –2
                                                                                                                                                  Потому что всегда считал, что вариант с range медленней. Теперь буду знать, что это не так, спасибо :)
                                                                                                                                                • 0
                                                                                                                                                  Дополню, если добавить вначало прагму use integer (чтобы все вычисления были целочисленными), результат становится — 22 секунды

                                                                                                                                                  Кстати, по поводу руби-скрипта который выполнялся 30 сек а не 200, подозреваю что у человека просто мощный процессор, у меня вот например — core 2 duo 6850, там что на тестовой конфигурации автора топика думаю будет раза в 2-3 дольше выполнятся
                                                                                                                                                  • +7
                                                                                                                                                    ну и ещё на секунду улучшим результат и сделаем его более Perl-way:

                                                                                                                                                    #!/usr/bin/perl
                                                                                                                                                    use integer;
                                                                                                                                                    use Benchmark;
                                                                                                                                                    $t = timeit(1,sub {
                                                                                                                                                        $r = 0;
                                                                                                                                                        for my $i (0..9999) {
                                                                                                                                                          for my $j (0..9999) {
                                                                                                                                                            $r += $i * $j 100;
                                                                                                                                                            $r %= 47;
                                                                                                                                                          }
                                                                                                                                                        }
                                                                                                                                                        print "answer: $r\n";    
                                                                                                                                                    });
                                                                                                                                                                   
                                                                                                                                                    print "time: ",timestr($t);

                                                                                                                                                    • –7
                                                                                                                                                      Действительно, красиво, спасибо.
                                                                                                                                                      Но на такой код уже менять, наверное не буду, т.к. по-моему, это уже «хак» ;)
                                                                                                                                                      • +7
                                                                                                                                                        В каком месте «хак»?
                                                                                                                                                        Так и должна выглядеть программа на языке Perl,
                                                                                                                                                        правда тут с Benchmark'ом, т.е. программа сама замеряет сколько времени этот код выполняется,
                                                                                                                                                        ну от него легко избавиться.

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

                                                                                                                                                        Опять же — psycho для питона — хак, а тут — pure Perl, никаких библиотек внешних даже нету… используется только стандартная прагма
                                                                                                                                                        • –3
                                                                                                                                                          Для python и perl описал под диаграммой возможности дополнительного ускорения.
                                                                                                                                                          Но, чёрт возьми, ведь в самом начале хотелось без «заточки кода» под каждый конкретный язык, сравнение просто общих операций :)

                                                                                                                                                          ps: а можно ли при использовании «use integer» пользоваться вычислениями с плавающей точкой? или более точно определять типы переменных?
                                                                                                                                                          • +3
                                                                                                                                                            > Но, чёрт возьми, ведь в самом начале хотелось без «заточки кода» под каждый конкретный язык, сравнение просто общих операций :)

                                                                                                                                                            Для общие операции в каждом языке свои общие общепринятые (и даже идиоматические) способы выражения. :)
                                                                                                                                                          • 0
                                                                                                                                                            Типов переменных как таковых в перле нет. Эта прагма отключает вычисления с плавающей точкой в текущем блоке кода, соответственно все вычисления происходят быстрее.

                                                                                                                                                            Прагмы в Perl действуют в пределах блока кода где они объявлены, в любой момент их можно отменить (no integer, например).

                                                                                                                                                            В частности эта — документирована (то есть присутствует в официальной документации) и является фичей языка (коих там много =) ), целью которой является ускорение частей когда где используется ТОЛЬКО целочисленная арифметика.
                                                                                                                                                            • 0
                                                                                                                                                              сама идея пела состоит с том, что это можно сделать разными способами, и оформление код влияет. (:
                                                                                                                                                    • +1
                                                                                                                                                      Мои результаты и 5 копеек :)
                                                                                                                                                      Оригинальный перл скрипт — 42.323s
                                                                                                                                                      вариант что выше но без «my» — 31.186s
                                                                                                                                                      вариант с «my» — 29.767s

                                                                                                                                                      кстати не знал что my такой полезный в этом плане, кстате почему ??
                                                                                                                                                      perl, v5.8.8
                                                                                                                                                      • 0
                                                                                                                                                        Только вот сидел я, тоже это заметил =)
                                                                                                                                                        • –1
                                                                                                                                                          5.8.8 потому что активно на Perl я не разрабатываю, а в системе (gentoo) что после «emerge world» обновилось, то и работает…
                                                                                                                                                          • 0
                                                                                                                                                            Не настолько хорошо знаком с внутренностями интерпретатора, но могу сделать предположение: следить за локальными переменными «проще», чем за глобальными. Как и в случае с Python.
                                                                                                                                                        • 0
                                                                                                                                                          Ruby-пример на моей системе (С2D 2.66) отработал за 21 секунду.

                                                                                                                                                          $ sudo nice -n -9 time ruby 1.rb
                                                                                                                                                          answer: 39
                                                                                                                                                          20.99 real 20.81 user 0.05 sys


                                                                                                                                                          Версия руби:

                                                                                                                                                          $ ruby -v
                                                                                                                                                          ruby 1.9.1p129 (2009-05-12 revision 23412) [i386-darwin9]