Как стать автором
Обновить

Простой тест llvm/libjit часть III, теперь еще и parrot

Время на прочтение3 мин
Количество просмотров883
Эта статья является продолжением статей:
Простой тест libjit vs llvm
Простой тест llvm/libjit часть II, те же + gnu lightning .

Вступительный реверанс



В предыдущих статьях рссматривалась производительность llvm, libjit и gnu lightning на примере решета эратосфена. Все из рассмотренных вариантов — низкоуровневые библиотеки, которые имеют хорошую скорострельность, но по существу являются специализированными ассемблерами, и, например, работу со строками придется реализовывать самому.

Есть и другие виртуальные машины, которые можно включить в свою программу в качестве backend для своих DSL. Например — родившийся в результате первоапрельской шуткиparrot — основа будущего перла.

Там возможностей — намного больше, включая строки, хэш-таблицы, безразмерные массивы, garbage collection, консольный и файловый ввод-вывод и другие приятные вещи. Вопрос — какова цена (в потере производительности) за все эти приятные добавления?

Давайте попробуем.

Решето эратосфена на parrot


Как и прежде — это две процедуры, одна из них (erato) реализует сам алгоритм, вторая (main) запускает 100_000 раз erato для поиска простых чисел от 1 до 50_000.

.loadlib 'trans_ops'
.loadlib 'math_ops'

.sub 'erato'
.param int n
$P0 = new 'ResizableIntegerArray' # a = P0
$P0 = n
$N0 = sqrt n # q = I0
$I0 = floor $N0 # i = I1
$I1 = 2
for_cond:
if $I1 > $I0 goto for_end
$I2 = $P0[$I1]
if $I2 == 1 goto end_if
$I3 = $I1 * $I1 # j = I3
while_cond:
if $I3 > n goto while_end
$P0[$I3] = 1
$I3 += $I1
goto while_cond
while_end:
end_if:
$I1 += 1
goto for_cond
for_end:
.end

.sub main :main
$I10 = 0
for_test1:
if $I0>100000 goto for_end1
erato(50000)
$I0 += 1
goto for_test1
for_end1:
.end



И — управляющая программа, которая все это запускает:

001:  #include <parrot/embed.h>
002:  #include <parrot/extend.h>
003:  

004:  int main(int argc, char* argv[])
005:  {
006:          Parrot_Interp interp;
007:          Parrot_PackFile pf;
008:  
009:          interp = Parrot_new(NULL);
010:          if (!interp) {
011:              return 1;
012:          }
013:  
014:          pf = Parrot_pbc_read(interp, "erato.pbc"0);
015:          Parrot_pbc_load(interp, pf);
016:          Parrot_runcode(interp, argc, argv);
017:  
018:          Parrot_destroy(interp);
019:  
020:          return 0;
021:   }
022:  


Итак, компиляция нового варианта:
parrot -o erato.pbc erato.ptr
gcc -O2 erato.c -I /usr/include/parrot/2.0.0/ -lparrot -o erato

И запуск:
/usr/bin/time -f "%U" ./erato
2361.2

Продукты и плоды авторского движения мысли


Итого, наша таблица приобретает вид:

VM Время выполнения в секундах, (меньше=лучше)
LLVM 13.77
LIBJIT 14.17
GNU LIGHTNING 32.59
PARROT 2361
И просто для информации:
gcc -O0 50.09
gcc -O1 13.79
аналогичная программа на perl 4288


То есть виртуальная машина parrot работает на нашем примере в 150 раз медленнее, чем jit машины. Но в 2 раза быстрее, чем программа на перле. Это на самом деле хорошая новость, похоже следующие версии перла, на основе parrot, собираются работать быстрее чем сегодня… Однако parrot явно не замена других рассмотреных машин, если нужна скорость.

Заключительный аккорд



В общем parrot оставил _очень_ приятное впечатление, все работает так, как описано, подводных камней не попалось, возможностей — море, и документация хорошая. Писать на нем после llvm — доставляет удовольствие. Так что для себя я составил примерно такие рекоммендации:

  • нужна скорость — llvm или libjit, llvm предпочтительнее (лучше инфраструктура, больше иструментов)
  • стесненные условия, например мало памяти и места на диске — gnu lightning;
  • если скорость не слишком важна, но нужно удобство, работа со строками или сложные структуры — parrot
Теги:
Хабы:
Всего голосов 4: ↑2 и ↓20
Комментарии3

Публикации