Эта статья является продолжением статей:
Простой тест libjit vs llvm
Простой тест llvm/libjit часть II, те же + gnu lightning .
В предыдущих статьях рссматривалась производительность llvm, libjit и gnu lightning на примере решета эратосфена. Все из рассмотренных вариантов — низкоуровневые библиотеки, которые имеют хорошую скорострельность, но по существу являются специализированными ассемблерами, и, например, работу со строками придется реализовывать самому.
Есть и другие виртуальные машины, которые можно включить в свою программу в качестве backend для своих DSL. Например — родившийся в результате первоапрельской шутки — parrot — основа будущего перла.
Там возможностей — намного больше, включая строки, хэш-таблицы, безразмерные массивы, garbage collection, консольный и файловый ввод-вывод и другие приятные вещи. Вопрос — какова цена (в потере производительности) за все эти приятные добавления?
��авайте попробуем.
Как и прежде — это две процедуры, одна из них (erato) реализует сам алгоритм, вторая (main) запускает 100_000 раз erato для поиска простых чисел от 1 до 50_000.
И — управляющая программа, которая все это запускает:
Итак, компиляция нового варианта:
И запуск:
Итого, наша таблица приобретает вид:
То есть виртуальная машина parrot работает на нашем примере в 150 раз медленнее, чем jit машины. Но в 2 раза быстрее, чем программа на перле. Это на самом деле хорошая новость, похоже следующие версии перла, на основе parrot, со��ираются работать быстрее чем сегодня… Однако parrot явно не замена других рассмотреных машин, если нужна скорость.
В общем parrot оставил _очень_ приятное впечатление, все работает так, как описано, подводных камней не попалось, возможностей — море, и документация хорошая. Писать на нем после llvm — доставляет удовольствие. Так что для себя я составил примерно такие рекоммендации:
Простой тест 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
