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

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

Модератор: Olej

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

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

Непрочитанное сообщение Olej » 17 фев 2014, 00:05

язык PHP
Реализация PHP (файл fibo.php):

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

#!/usr/bin/php 
<?php 

function fib( $n ) { 
   return $n < 2 ? 1 : fib( $n - 1 ) + fib( $n - 2 ); 
} 

echo fib( $argv[ 1 ] ), "\n"; 
?> 
Выполнение приложения:

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

$ php --version 
PHP 5.4.4-14+deb7u7 (cli) (built: Dec 12 2013 10:55:22) 
Copyright (c) 1997-2012 The PHP Group 
Zend Engine v2.4.0, Copyright (c) 1998-2012 Zend Technologies 
# time nice -9 php fibo.php 30 
1346269 
real	0m12.472s 
user	0m1.572s 
sys	0m0.008s 
# time nice -9 php fibo.php 30 
1346269 
real	0m12.641s 
user	0m1.588s 
sys	0m0.000s 
# time nice -9 php fibo.php 30 
1346269 
real	0m13.245s 
user	0m1.568s 
sys	0m0.012s 
Здесь результат почти в 2 раза хуже чем JavaScript и Ruby, и приближается (чуть меньше) к Python. Этот код медленнее нативного C почти в 100 раз.

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

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

Непрочитанное сообщение Olej » 17 фев 2014, 00:06

язык Lua
Реализация задачи на языке Lua (файл fibo.lua):

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

#!/usr/bin/lua 

fib = function( n ) -- функциональный литерал 
         if( n < 2 ) then 
            return 1 
         else 
            return fib( n - 1 ) + fib( n - 2 ) 
         end 
      end 

print( fib( arg[ 1 ] + 0 ) ) 
Выполнение такого приложения (с проверкой версии Lua):

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

$ lua 
Lua 5.2.1  Copyright (C) 1994-2012 Lua.org, PUC-Rio 
> 
# time nice -9 lua fibo.lua 30 
1346269 
real	0m7.964s 
user	0m0.636s 
sys	0m0.004s 
# time nice -9 lua fibo.lua 30 
1346269 
real	0m8.194s 
user	0m0.636s 
sys	0m0.000s 
# time nice -9 lua fibo.lua 30 
1346269 
real	0m8.336s 
user	0m0.640s 
sys	0m0.000s 
Это те же результаты, что и у JavaScript и Ruby.

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

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

Непрочитанное сообщение Olej » 17 фев 2014, 00:15

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

Можно ли организовать подобные вычисления в интерпретаторе bash, учитывая, что функции bash могут возвращать только значения кода завершения в пределах [0...255], т. е. в нашем смысле — не имеющие возвращаемых вычисленных значений?
Наверняка можно, в IT можно всё, но это может оказаться довольно изощрённо... (может я на досуге сделаю и покажу такое решение).
Но можно организовать подобные вычисления, если сам скрипт будет рекурсивно вызывать свои копии. Вот только то и всего:

Реализация задачи в bash (файл fido.sh):

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

#!/bin/bash 

if [ "$1" -lt "2" ] 
then 
   echo "1" 
else 
   f1=$($0 `expr $1 - 1`) 
   f2=$($0 `expr $1 - 2`) 
   echo `expr $f1 + $f2` 
fi 
Я не рискну вызывать такое решение с аргументом 30 (как остальные варианты) — я просто не дождусь решения... Но выполняется такого скрипт вполне успешно:

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

$ bash --version 
GNU bash, version 4.2.37(1)-release (i486-pc-linux-gnu) 
…
# time nice -9 ./fibo.sh 8 
34 
real	0m5.814s 
user	0m0.024s 
sys	0m0.040s 
# time nice -9 ./fibo.sh 10 
89 
real	0m16.574s 
user	0m0.124s 
sys	0m0.068s 
# time nice -9 ./fibo.sh 12 
233 
real	0m41.785s 
user	0m0.364s 
sys	0m0.232s 
Получается, что скрипт bash вычисляет функцию от 8 столько же, сколько не очень «спешному» Perl требуется для вычисления функции от 26 (это при экспоненциальном то росте!):

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

# time nice -9 perl fibo.pm 26 
196418 
real	0m5.775s 
user	0m0.396s 
sys	0m0.000s 
... это если грубо прикинуть по оценкам сложности (вначале: 10 раз на каждые +5) то значение для 30 скрипт должен вычислять порядка 16 * 10^4 сек. ... 16000 или 4-5 часов :-o

Практического смысла показанная реализация на bash не имеет, но сама такая возможность интересна.

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

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

Непрочитанное сообщение Olej » 17 фев 2014, 00:18

язык Go
Реализация теста на языке Go (файл fido_go.go):

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

package main 

import ( 
   "fmt"; "os"; "strconv" 
) 

func fib ( n int ) int { 
   if n < 2 { 
      return 1 
   } else { return fib( n - 1 ) + fib( n - 2 ) } 
} 

func main(){ 
   n, _ := strconv.Atoi( os.Args[ 1 ] ) 
   fmt.Println( fib( n ) ) 
} 
Сборка и выполнения этой программы (с демонстрацией используемой версии):

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

$ gccgo --version 
gccgo (Debian 4.7.2-5) 4.7.2 
Copyright (C) 2012 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions.  There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
$ gccgo fibo_go.go -o fibo_go 
# time nice -9 ./fibo_go 30 
1346269 
real   0m0.392s 
user   0m0.020s 
sys    0m0.008s 
# time nice -9 ./fibo_go 30 
1346269 
real   0m0.383s 
user   0m0.020s 
sys    0m0.004s 
# time nice -9 ./fibo_go 30 
1346269 
real   0m0.367s 
user   0m0.020s 
sys    0m0.008s 
И вот здесь маленький и не очень пока отточенный из-за своей новизны Go, показывает замечательный результат: без всякой оптимизации всего в 2.5 раза медленнее GCC, и быстрее, чем Clang!

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

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

Непрочитанное сообщение Olej » 17 фев 2014, 00:31

язык Ocaml
Реализация теста на языке Ocaml (файл fido_ml.ml):

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

let rec fib n = 
  if n < 2 then 1 else fib( n - 1 ) + fib( n - 2 );; 

let main () = 
  let arg = int_of_string Sys.argv.( 1 ) in 
  print_int( fib arg ); 
  print_newline(); 
  exit 0;; 

main ();; 
Но этот код можно Ocaml можно выполнять двояким способом … посредством его интерпретации:

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

$ ocaml -version 
The Objective Caml toplevel, version 3.12.1 
# time nice -9 ocaml fibo_ml.ml 30 
1346269 
real	0m2.332s 
user	0m0.196s 
sys	0m0.004s 
# time nice -9 ocaml fibo_ml.ml 30 
1346269 
real	0m2.067s 
user	0m0.188s 
sys	0m0.000s 
# time nice -9 ocaml fibo_ml.ml 30 
1346269 
real	0m2.188s 
user	0m0.192s 
sys	0m0.004s 
Или откомпилировав его в машинный код:

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

$ ocamlc -o fibo_ml fibo_ml.ml
# time nice -9 ./fibo_ml 30 
1346269 
real	0m2.016s 
user	0m0.180s 
sys	0m0.000s 
# time nice -9 ./fibo_ml 30 
1346269 
real	0m2.043s 
user	0m0.180s 
sys	0m0.004s 
# time nice -9 ./fibo_ml 30 
1346269 
real	0m2.0458s 
user	0m0.180s 
sys	0m0.000s 
Вообще то, по времени выполнения это практически идентичные варианты. Это наталкивает на мысль, что интерпретатор Ocaml работает с предкомпиляцией (JIT), а компилированная форма — это тот же байт-код с прикомпонованной к нему исполняющей системой.
Здесь время хуже C в 25 раз, даже хуже Java в 1.5 раза, но лучше всех рассматривавшихся интерпретирующих языков.

Аватара пользователя
Lepton
Писатель
Сообщения: 73
Зарегистрирован: 18 окт 2011, 20:26
Контактная информация:

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

Непрочитанное сообщение Lepton » 17 фев 2014, 15:57

PureBasic (v5.0)

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

Dim Fibonacci.i(Val(ProgramParameter(0)))
Fibonacci(0) = 1
Fibonacci(1) = 1
For n=2 To Val(ProgramParameter(0))
  Fibonacci(n) = Fibonacci(n-1) + Fibonacci(n-2)
Next
Print (Str(Fibonacci(Val(ProgramParameter(0)))))
Выхлоп

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

time nice -9 ./fibo_pb 30
1346269
real	0m0.004s
user	0m0.000s
sys	 0m0.000
Для сравнения

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

time nice -9 ./fibo_cc 30
1346269
real	0m0.017s
user	0m0.016s
sys	 0m0.000s
или

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

time nice -9 ./fibo_cc 50
20365011074
real	1m8.678s
user	1m8.668s
sys	 0m0.004s

time nice -9 ./fibo_pb 50
20365011074
real	0m0.004s
user	0m0.000s
sys 	0m0.000
:-D

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

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

Непрочитанное сообщение Olej » 17 фев 2014, 18:12

Lepton писал(а):PureBasic (v5.0)

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

Dim Fibonacci.i(Val(ProgramParameter(0)))
Fibonacci(0) = 1
Fibonacci(1) = 1
For n=2 To Val(ProgramParameter(0))
  Fibonacci(n) = Fibonacci(n-1) + Fibonacci(n-2)
Next
Print (Str(Fibonacci(Val(ProgramParameter(0)))))
А где вы его такой взяли, PureBasic?
Это что за зверь такой? ;-)

Аватара пользователя
Lepton
Писатель
Сообщения: 73
Зарегистрирован: 18 окт 2011, 20:26
Контактная информация:

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

Непрочитанное сообщение Lepton » 17 фев 2014, 19:17

Olej писал(а):
Lepton писал(а):PureBasic (v5.0)
А где вы его такой взяли, PureBasic?
Это что за зверь такой? ;-)
Разновидность языка Basic с платным компилятором (Linux, Windows, MacOS X, AmigaOS) но не все так плохо - есть демо версия, полностью работоспособная, но компилит не более 800 строк. Для небольших утилит самое то. :-)
http://www.purebasic.com/
Сейчас версия 5.21

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

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

Непрочитанное сообщение Olej » 17 фев 2014, 19:36

Olej писал(а):язык сценариев bash
... да, именно bash, потому что я его показывал в сравнительном ряду кодов, пусть он будет и здесь.

Можно ли организовать подобные вычисления в интерпретаторе bash, учитывая, что функции bash могут возвращать только значения кода завершения в пределах [0...255], т. е. в нашем смысле — не имеющие возвращаемых вычисленных значений?
Наверняка можно, в IT можно всё, но это может оказаться довольно изощрённо... (может я на досуге сделаю и покажу такое решение).
Вот такое славненькое решение:

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

#!/bin/bash

declare -a res

fib () {
   if [ "$1" -lt 2 ]
   then
      res[ $1 ]=1.
   else.
      fib `expr $1 - 1`
      let s=${res[ `expr $1 - 1` ]}+${res[ `expr $1 - 2` ]}
      res[ $1 ]=$s
   fi
}

res[ 0 ]=1
fib $1
echo ${res[ $1 ]}
Сравнение аналогичное предыдущим:

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

root@notebook:/home/olej/2014_WORK/OWN.BOOKS/ManyLan/ex.draft/speed# time nice -9 ./fibo_c 30
1346269
real   0m0.016s
user   0m0.008s
sys    0m0.004s
root@notebook:/home/olej/2014_WORK/OWN.BOOKS/ManyLan/ex.draft/speed# time nice -9 ./fibo_f.sh 30
1346269
real   0m0.158s
user   0m0.008s
sys    0m0.012s
Но ... это сравнение нечестное! Потому что:

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

root@notebook:/home/olej/2014_WORK/OWN.BOOKS/ManyLan/ex.draft/speed# time nice -9 ./fibo_c 40
165580141
real	0m1.292s
user	0m0.940s
sys	0m0.004s
root@notebook:/home/olej/2014_WORK/OWN.BOOKS/ManyLan/ex.draft/speed# time nice -9 ./fibo_f.sh 40
165580141
real	0m0.174s
user	0m0.016s
sys	0m0.008s
root@notebook:/home/olej/2014_WORK/OWN.BOOKS/ManyLan/ex.draft/speed# time nice -9 ./fibo_f.sh 50
20365011074
real	0m0.205s
user	0m0.004s
sys	0m0.024s
При N=40 shell-скрипт уже обгоняет C нативное приложение ... а при N=50 и подавно :-o , и численные результаты верные!

Фокус в том, что этот shell-скрипт по честному вызывает функцию fib() рекурсивно, но рекурсивно 1 раз в выражении fib(N)=fib(N-1)+fib(N-2), поэтому его дерево рекурсивных вызовов растёт медленнее, и в комбинаторно медленнее раз. А это очень серьёзно!

Такую оптимизацию можно было бы легко произвести для примеров на каждом языке! ... но я стремился (так написано в 1-м сообщении темы) то к обратному.

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

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

Непрочитанное сообщение Olej » 17 фев 2014, 19:43

Lepton писал(а):
Olej писал(а):
Lepton писал(а):PureBasic (v5.0)
А где вы его такой взяли, PureBasic?
Это что за зверь такой? ;-)
Разновидность языка Basic с платным компилятором (Linux, Windows, MacOS X, AmigaOS) но не все так плохо - есть демо версия, полностью работоспособная, но компилит не более 800 строк. Для небольших утилит самое то. :-)
http://www.purebasic.com/
Сейчас версия 5.21
Я обязательно посмотрю...
Но в примере и его результатах у вас - обман ;-) : у вас числа Фибоначчи вычисляются прямым движением по массиву, от 2 до N ... а не двумя деревьями рекурсивных вызовов.
Так и я могу :lol:
Но это не годится для сравнений.

Но обязательно посмотрю... , спасибо.
Только на пока у меня первейший пункт программы: снести нафиг Debian и переустановить систему на Fedora 20 ;-) ... После чего обязательно посмотрю, скачаю, проверю.

Ответить

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

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

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