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

Вопросы написания собственного программного кода (на любых языках)

Модератор: Olej

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

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

Непрочитанное сообщение Olej » 16 фев 2014, 22:34

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

В принципе, любые сравнения производительности приложений на разных языках довольно бессмысленно, потому что очень сильно зависит от характера задачи: одни языки будут иметь относительно лучшую скорость на счётных задачах, кто-то на вещественных, кто-то на целочисленных; другие языки - на разборе текстовой информации, регулярных выражениях, третьи - на синтаксическом и лексическом анализе... Т.е. оценивать скорость - бессмысленно, можно оценивать порядок скорости: если компилирующий C экспериментально быстрее интерпретирующего PHP в 130 раз, то тут не важно это 100 раз, или 200 раз - это 2 порядка. Но если так, то почти всё равно какую выбрать задачу для оценивания.

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

Мне нравится в этом смысле задача вычисления чисел Фибоначчи ... только когда она алгоритмируется "в лоб", без всяких оптимизаций:

Код: Выделить всё

fib( N ) =
... 1 если N < 2
... если N > 2 то fib( N - 1 ) + fib( N - 2 )
Вот в такой формулировке я готов прогнать это вычисление через десяток-другой языков программирования. :lol:

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: производительность языков программирования

Непрочитанное сообщение Olej » 16 фев 2014, 23:22

Olej писал(а): Второй критерий - задача должна бы иметь как можно большую степень роста вычислительной сложности от её размерности. Лучше всего бы- экспоненциальную степень сложности... или выше :shock: . Как раз то, чего все боятся и все борются.
Прикинул я такой тестик: степень вычислительной сложности этой задачи от размерности (на Python):

Код: Выделить всё

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys

c = 0

def fib( n ) :
    global c
    c += 1
    if n < 2 : return 1
    else: return fib( n - 1 ) + fib( n - 2 )

# тест степени роста вычислительной сложности от N
n = int( sys.argv[ 1 ] )
f = fib( int( sys.argv[ 1 ] ) )
print( "n={} - число вызовов {}".format( n, c ) )
Ну и цифры показывают то что надо:

Код: Выделить всё

olej@notebook:~/2014_WORK/OWN.BOOKS/ManyLan/ex.draft/speed$ ./O-test.py 5
n=5 - число вызовов 15
olej@notebook:~/2014_WORK/OWN.BOOKS/ManyLan/ex.draft/speed$ 10
bash: 10: команда не найдена
olej@notebook:~/2014_WORK/OWN.BOOKS/ManyLan/ex.draft/speed$ ./O-test.py 10
n=10 - число вызовов 177
olej@notebook:~/2014_WORK/OWN.BOOKS/ManyLan/ex.draft/speed$ ./O-test.py 20
n=20 - число вызовов 21891
olej@notebook:~/2014_WORK/OWN.BOOKS/ManyLan/ex.draft/speed$ ./O-test.py 25
n=25 - число вызовов 242785
olej@notebook:~/2014_WORK/OWN.BOOKS/ManyLan/ex.draft/speed$ ./O-test.py 30
n=30 - число вызовов 2692537
При росте размерности (N) на +5 вычислительная сложность растёт на порядок, в 10 раз.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: производительность языков программирования

Непрочитанное сообщение Olej » 16 фев 2014, 23:27

Язык C

Код: Выделить всё

#include <stdio.h> 

unsigned long fib( int n ) { 
   return n < 2 ? 1 : fib( n - 1 ) + fib( n - 2 ); 
} 

int main( int argc, char **argv ) { 
   unsigned num = atoi( argv[ 1 ] ); 
   printf( "%ld\n", fib( num ) ); 
   return 0; 
} 
Выполнение:

Код: Выделить всё

$ gcc --version 
gcc (Debian 4.7.2-5) 4.7.2 
...
# time nice -9 ./fibo_c 30 
1346269 
real   0m0.146s 
user   0m0.008s 
sys   0m0.000s 
# time nice -9 ./fibo_c 30 
1346269 
real   0m0.175s 
user   0m0.012s 
sys   0m0.000s 
# time nice -9 ./fibo_c 30 
1346269 
real   0m0.151s 
user   0m0.008s 
sys   0m0.000s
Язык C - это будет эталоном для сравнения с другими языками ... вряд ли ещё найдётся язык-компилятор, которые произведут более эффективный код.

Запуск делаю:
- от root чтобы иметь право nice
- nice повышаю приоритет, чтобы как-то повысить повторяемость результатов
- повторяемость, устойчивость результатов, как видно, достаточно хорошая.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: производительность языков программирования

Непрочитанное сообщение Olej » 16 фев 2014, 23:33

язык C++
компилятор GCC

Реализация будет выглядеть так:

Код: Выделить всё

#include <iostream> 
#include <stdlib.h> 
using namespace std; 

unsigned long fib( int n ) { 
  return n < 2 ? 1 : fib( n - 1 ) + fib( n - 2 ); 
} 

int main( int argc, char **argv ) { 
   unsigned num = atoi( argv[ 1 ] ); 
   cout << fib( num ) << endl; 
   return 0; 
} 
Из этого единого кода будет создано 2 приложения — компиляцией GCC и компиляцией Clang:
Сборка:

Код: Выделить всё

$ g++ -O3 fibo_cc.cc -o fibo_cc 
$ clang++ fibo_cc.cc -o fibo_cl 
Выполнение приложения, собранного GCC:

Код: Выделить всё

# time nice -9 ./fibo_cc 30 
1346269 
real   0m0.125s 
user   0m0.012s 
sys    0m0.000s 
# time nice -9 ./fibo_cc 30 
1346269 
real   0m0.152s 
user   0m0.008s 
sys    0m0.004s 
# time nice -9 ./fibo_cc 30 
1346269 
real   0m0.171s 
user   0m0.008s 
sys    0m0.004s 
Здесь время абсолютно равное случаю реализации C, в пределах статистической погрешности. И трудно было ожидать иного, а с чего бы ему отличаться? ;-)

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: производительность языков программирования

Непрочитанное сообщение Olej » 16 фев 2014, 23:38

язык C++
компилятор GCC

Я уже выше показал, что из этого кода было 2 сборки:
Olej писал(а): Сборка:

Код: Выделить всё

$ g++ -O3 fibo_cc.cc -o fibo_cc 
$ clang++ fibo_cc.cc -o fibo_cl 
Результат выполнения приложения, собранного Clang:

Код: Выделить всё

$ clang --version 
Debian clang version 3.0-6.2 (tags/RELEASE_30/final) (based on LLVM 3.0) 
Target: i386-pc-linux-gnu 
Thread model: posix 
# time nice -9 ./fibo_cl 30 
1346269 
real   0m0.470s 
user   0m0.032s 
sys    0m0.004s 
# time nice -9 ./fibo_cl 30 
1346269 
real   0m0.481s 
user   0m0.040s 
sys    0m0.000s 
# time nice -9 ./fibo_cl 30 
1346269 
real   0m0.522s 
user   0m0.036s 
sys    0m0.000s 
Здесь всё гораздо хуже! Это в 3.2 раза медленнее, чем для GCC. Но в объяснение можно привести следующее:
  • использована достаточно старая версия Clang (не делалось свежей установки), а утверждается, что Clang имеет соизмеримую с GCC эффективность кода, и даже временами превосходит его, начиная с версии 3.2;
  • в команде компиляции Clang вообще не устанавливалась опция оптимизации (-O...) ... я пока просто не знаю как ней с толком распорядиться;

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: производительность языков программирования

Непрочитанное сообщение Olej » 16 фев 2014, 23:45

язык Java
Реализация задачи на Java (fibo.java):

Код: Выделить всё

public class fibo { 
   public static long fib( int n ) { 
      return n < 2 ? 1 : fib( n - 1 ) + fib( n - 2 ); 
   } 

   public static void main( String[] args ) { 
      int num = new Integer( args[ 0 ] ).intValue(); 
      System.out.println( fib( num ) ); 
   } 
} 
Компиляция приложения выполняется в реализации OpenJDK:

Код: Выделить всё

$ java -version 
java version "1.6.0_27" 
OpenJDK Runtime Environment (IcedTea6 1.12.6) (6b27-1.12.6-1~deb7u1) 
OpenJDK Client VM (build 20.0-b12, mixed mode, sharing) 
$ javac fibo.java 
$ ls -l *.class 
-rw-r--r-- 1 olej olej 594 Фев 15 16:09 fibo.class 
Если то же самое проделать с оригинальном Oracle JDK, то временные результаты могут отличаться.
Выполнение:

Код: Выделить всё

# time nice -9 java fibo 30 
1346269 
real   0m1.295s 
user   0m0.096s 
sys    0m0.020s 
# time nice -9 java fibo 30 
1346269 
real   0m1.320s 
user   0m0.092s 
sys    0m0.020s 
# time nice -9 java fibo 30 
1346269 
real   0m1.262s 
user   0m0.092s 
sys    0m0.016s
Выполнение JVM байт-кода Java здесь в 8.6 раз медленнее, чем компилированного в машинные команды кода C.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: производительность языков программирования

Непрочитанное сообщение Olej » 16 фев 2014, 23:48

язык Python
Реализация на Python (fibo.py):

Код: Выделить всё

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

import sys 

def fib( n ) : 
    if n < 2 : return 1 
    else: return fib( n - 1 ) + fib( n - 2 ) 

n = int( sys.argv[ 1 ] ) 
print( "{}".format( fib( int( sys.argv[ 1 ] ) ) ) ) 
Для этого кода (он написан в совместимом синтаксисе) нужно смотреть 2 различных способа исполнения:
- Python версии 2:

Код: Выделить всё

$ python --version 
Python 2.7.3 
# time nice -9 python fibo.py 30 
1346269 
real   0m14.296s 
user   0m1.136s 
sys    0m0.000s 
# time nice -9 python fibo.py 30 
1346269 
real   0m14.519s 
user   0m1.144s 
sys    0m0.004s 
# time nice -9 python fibo.py 30 
1346269 
real   0m14.264s 
user   0m1.120s 
sys   0m0.016s 
- Python версии 3:

Код: Выделить всё

$ python3 --version 
Python 3.2.3 
# time nice -9 python3 fibo.py 30 
1346269 
real   0m17.532s 
user   0m1.444s 
sys    0m0.008s 
# time nice -9 python3 fibo.py 30 
1346269 
real   0m17.748s 
user   0m1.468s 
sys    0m0.004s 
 # time nice -9 python3 fibo.py 30 
1346269 
real   0m18.043s 
user   0m1.440s 
sys    0m0.016s
Первое, что здесь сразу бросается в глаза: Python 2 быстрее Python 3 на 25%. Это достаточно ожидаемо — это естественная плата за существенно расширенный синтаксис. Ряд публикаций показывают и даже существенно большую разницу на определённых классах задач, до 2-х или 3-х раз.
А вот в сравнении с нативным компилированным кодом C Python 2 проигрывает почти 100 (95) раз! Это тоже соответствует тому, что звучит в публикациях.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: производительность языков программирования

Непрочитанное сообщение Olej » 16 фев 2014, 23:52

язык Ruby
Реализация задачи на Ruby (fibo.rb):

Код: Выделить всё

#!/usr/bin/ruby 
# coding: utf-8 

def fib( n ) 
   return n < 2 ? 1 : fib( n - 1 ) + fib( n - 2 ) 
end 

puts fib( ARGV[ 0 ].to_i ) 
Выполнение:

Код: Выделить всё

$ ruby --version 
ruby 1.9.3p194 (2012-04-20 revision 35410) [i486-linux] 
# time nice -9 ruby fibo.rb 30 
1346269 
real	  0m7.949s 
user	  0m0.732s 
sys	  0m0.000s 
# time nice -9 ruby fibo.rb 30 
1346269 
real	  0m8.164s 
user	  0m0.736s 
sys	  0m0.004s 
# time nice -9 ruby fibo.rb 30 
1346269 
real	  0m8.234s 
user	  0m0.720s 
sys	  0m0.008s 
Здесь время выполнение, на удивление (непонятно почему), примерно в 2 раза лучше, чем у Python, и медленнее нативного кода C примерно в 50 раз.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: производительность языков программирования

Непрочитанное сообщение Olej » 16 фев 2014, 23:57

язык Perl
Реализация задачи на Perl (fibo.pm):

Код: Выделить всё

#!/usr/bin/perl 

sub fib { 
  my $n = shift; 
  $n < 2 ? 1 : fib( $n - 1 ) + fib( $n - 2 ) 
} 

$f = fib( $ARGV[ 0 ] ); 
print "$f\n"; 
Выполнение:

Код: Выделить всё

$ perl --version 
This is perl 5, version 14, subversion 2 (v5.14.2) built for i486-linux-gnu-thread-multi-64int 
(with 88 registered patches, see perl -V for more detail) 
Copyright 1987-2011, Larry Wall 
...
# time nice -9 perl fibo.pm 30 
1346269 
real   0m34.579s 
user   0m2.704s 
sys    0m0.004s 
# time nice -9 perl fibo.pm 30 
1346269 
real   0m36.880s 
user   0m2.712s 
sys    0m0.008s 
Здесь проигрыш нативному коду C составляет свыше 233 раз! Но это достаточно естественно и ожидаемо — Perl не язык для вычислений, и его ниша это текстовая обработка.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: производительность языков программирования

Непрочитанное сообщение Olej » 16 фев 2014, 23:58

язык JavaScript
Реализация на JavaScript (файл fibo.js):

Код: Выделить всё

#!/usr/bin/js -U 

var fib = function( n ) {  // функциональный литерал 
       return n < 2 ? 1 : fib( n - 1 ) + fib( n - 2 ); 
    } 

print( fib( arguments[ 0 ] ) )
Выполнение приложения (начиная с уточнения версии):

Код: Выделить всё

$ js -z | grep Version 
Error: Invalid short option: -z 
Version: JavaScript-C 1.8.5+ 2011-04-16 
# time nice -9 js fibo.js 30 
1346269 
real   0m6.962s 
user   0m1.176s 
sys    0m0.004s 
# time nice -9 js fibo.js 30 
1346269 
real   0m7.241s 
user   0m1.192s 
sys    0m0.004s 
# time nice -9 js fibo.js 30 
1346269 
real   0m7.841s 
user   0m1.212s 
sys    0m0.008s 
Этот результат удивил: это те же цифры, что и у Ruby, и в 2 раза лучше, чем Python. От нативного кода C здесь отставание в 50 раз.

Ответить

Вернуться в «Программирование»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 8 гостей