Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > Скорость работы скрипта


Автор: MakTpaxep 7.6.2011, 14:07
Ясно что интерптетатор работает медленнее откомпиленного кода.
Пришлось выбирать между скоростью разработки на perl и скоростью обработки здоровых файлов на c++.
Какие способы есть ускорить выполнение?

Первой мыслью было сделать независимый ехе.
Нашёл http://www.indigostar.com/perl2exe.php.
Подобрал под свою версию - конвертнуло, но при запуске пусто (сделал простой print "hi").
Попробовал другой версией - ошибки.
Кто-нибудь вообще пользовался этой крутейшей штукой? 
Я готов попариться ещё, но интересно намного ли станет быстрее?

Есть ли ещё какие-либо способы?

Кстати я так понял, что хэш в perl, вообще на парится о скорости доступа, а он у меня ипользуется.
Поищу как я ему замену..

Автор: sir_nuf_nuf 7.6.2011, 14:35
MakTpaxep, числа в студию.  Иначе все размышления - не имеют ценности.

У меня вот есть такие соображения
1) perl упакованный в exe будет не быстрее обычного скрипта, т.к. настоящей компиляции не происходит.
Только упаковка того же самого интерпретатора и скрипта в 1 файл. Максимум - съэкономите копейки на парсинге скрипта.
2) perl хеши - довольно быстрые, т.к. написаны на С, отлаживаются и улучшаются уже более 20 лет. 
Скорее всего время уходит не доступ к хешу а на что то еще..
Например на подготовку ключа:
Код

$hash{ "prefix_" . $id } = 1;



Есть способ - сделать профилирование (Devel::NYTProf)  скрипта и посмотреть на что уходит время.

Автор: afiskon 7.6.2011, 14:40
Цитата

Ясно что интерптетатор работает медленнее откомпиленного кода.


Сколько не компилируй сортировку пузырьком, скриптовая быстра сортировка более эффективна ;)
Цитата

Первой мыслью было сделать независимый ехе.

Плохая мысль. Все эти генераторы perl -> exe просто сжимают ваш скрипт и цепляют архив к интерпретатору.
Цитата

Кстати я так понял, что хэш в perl, вообще на парится о скорости доступа

Представляет собой обычное красно-черное дерево в памяти. В C++ map точно так же реализован.
Цитата

скоростью обработки здоровых файлов

Если вы углубитесь в историю создания Perl, то откроете, что этот язык как раз создавался для обработки больших объемов данных. Способы ускорения существуют, можете почитать о них (извините за самопиар) в http://eax.me/speed-matters/. Еще там есть несколько заметок про многопоточность.

Автор: EcSYZ 7.6.2011, 14:52
В заметке не нашёл вообще ничего, хоть как то связанного с ускорением.
Не знаю для чего там создавался перл, но на больших файлах он уже не особо быстро работает.
У меня есть скрипт, который разбирает кучу файлов с помощью регулярок. После многих тестов и сравнений, я заменил весь разбор файлов с перла на bash+cat+egrep. В итоге то что делалось на перле минуты 3 сократилось секунд до 10-20(но точных цифр я не помню, хотя эти не сильно далеки от истины).

Автор: MakTpaxep 7.6.2011, 14:56
Цитата(afiskon @  7.6.2011,  14:40 Найти цитируемый пост)
Представляет собой обычное красно-черное дерево в памяти. В C++ map точно так же реализован.

а я чёто думал что АВЛ. Ну да фиг с ним
Цитата(afiskon @  7.6.2011,  14:40 Найти цитируемый пост)
Если вы углубитесь в историю создания Perl, то откроете, что этот язык как раз создавался для обработки больших объемов данных.

А я думал что для небольших, но хитрозамученных отчётов) Реги действительно ускоряют работу в десятки раз, по сравнению с плюсами. Но на плюсах всё таки написанный код будет быстрее. Скоро сам заморочусь и проверю.
Цитата(afiskon @  7.6.2011,  14:40 Найти цитируемый пост)
Способы ускорения существуют, можете почитать о них (извините за самопиар) в этой заметке. Еще там есть несколько заметок про многопоточность.

Пост нештяк, но я к вебу пока что никакого отношения не имею) У меня xml, ну или если хотите txt.
Обработка идёт почти час!! Два файла метров по 13, получаются метров под 50. 
Цитата(sir_nuf_nuf @  7.6.2011,  14:35 Найти цитируемый пост)
Есть способ - сделать профилирование (Devel::NYTProf)  скрипта и посмотреть на что уходит время.

Спасибо, я погляжу.
Цитата

bash+cat+egrep.

Тоже гляну что за зверь эдакий)

Автор: arto 7.6.2011, 15:39
> После многих тестов и сравнений, я заменил весь разбор файлов с перла на bash+cat+egrep. В итоге то что делалось на перле минуты 3 сократилось секунд до 10-20

можно-ли увидеть скрипт?

Автор: EcSYZ 7.6.2011, 15:49
К сожалению - нельзя.
Это не совсем скрипт, скорее один проект, которым я занимаюсь.
Через веб загружался файл и после чего парсился, так что надо было свести к минимуму время парсинга.
Сначала у меня был цикл с кучей лишних регулярок и проверок, потом я его подправил и всемя сократилось вполне весомо. Но всё равно работало медленно, так что в поисках счастья я направился к bash, и сделал простой такой код:
Код

my $cmd = sprintf('cat "%s" | egrep -i "(%s)" > "%s"', $in_file, $pattern, $out_file);
`$cmd`;

который меня вполне обрадовал. Может позже руки дойдут и перепишу это на чистом c++, но пока некогда.

Автор: KSURi 7.6.2011, 16:03
Цитата(afiskon @  7.6.2011,  14:40 Найти цитируемый пост)
Представляет собой обычное красно-черное дерево в памяти. В C++ map точно так же реализован.

Структура данных для хешей так и называется - хеш-таблица. Внутри реализована с помощью связных списков.

Автор: arto 7.6.2011, 16:49
очень странно.

# a=$( date +"%s" ); find /usr/share -type f -print | xargs cat | egrep "(AAA|BBB|CCC)" &> /dev/null; print $[ $( date +"%s" )-$a ] 
131
# a=$( date +"%s" ); find /usr/share -type f -print | xargs cat | perl -ne "m#(?:AAA|BBB|CCC)# && print" &> /dev/null; print $[ $( date +"%s" )-$a ]
102
#

мне кажется, что вы что-то недоговариваете.
регулярное выражение можете привести?

Автор: EcSYZ 7.6.2011, 17:23
Хм, щас по новой прогнал разбор файлов.
По результатам получилось что перл был быстрее на 5 сек.
Х\з в чём прикол, может разница между 5.10 и 5.12.
Так что я признаю что щас перл по тестам быстрее, но от слов, что когда я это мутил bash был в разы быстрее я не собираюсь отказываться  smile 

Автор: afiskon 7.6.2011, 17:31
Цитата

а я чёто думал что АВЛ

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

Цитата

Структура данных для хешей так и называется - хеш-таблица. Внутри реализована с помощью связных списков.

Точно. Как я мог так заблуждаться! Раз ассоциативные массивы в Perl еще называют хэши, значит (о я дурааак!) и реализованы они на хэш-таблицах. Ага. Главное - сильно-сильно в это верить smile 

Автор: KSURi 7.6.2011, 17:43
Можно верить, а можно почитать соответствующие источники и убедиться самому.
Сарказм не к месту, т.к., действительно, не зря они называются хешами, а не ассоциативными массивами.

Автор: sir_nuf_nuf 7.6.2011, 18:05
Можно поступить даже проще
Код

print scalar %ENV;

Напечатает что то вроде 32/64.
Это соотношнение занятых и выделеных bucket (корзин) - структура которая имеет смысл только для хеш таблиц.

Автор: MakTpaxep 7.6.2011, 18:44
А как дела обстоят с повторной перекомпиляцией кода? Интерпретатор перекомпиливает одни и теже участки кода и реги по несколько раз? Если этого избегать, то разница в скорости не должна особо ощущаться. (Я чёто только сейчас задумался а так ли это - в голове вроде всегда было что скрипты это jit компиляция, потому медленнее).

Написал, потом подумал называется=(

Автор: Pfailed 7.6.2011, 20:20
MakTpaxep, регулярные выражения перекомпилируются только если в них содержится переменная и не указан модификатор /o

Автор: kavkaz 10.6.2011, 15:26
Разгонять perl скрипт можно.
Не сказать, что можно выиграть на порядок в скорости (ну, если там не совсем маразматичный код), но что-то делать можно.
Да, хэши вроде как и быстры, но они медленнее массива
Рекомендую освежить память, http://perldoc.perl.org/fields.html , что-то почерпнуть можно.
Ну и, алгоритм, его можно улучшать бесконечно.
Смотрите какая операция у вас самая частая - отталкивайтесь от этого.
Если можете обойтись без множественного вызова функции путем дублирования кода - дублируйте код (ой, за это меня казнят smile) ) - но, мы же оптимизируем скорость smile 

Автор: arto 10.6.2011, 16:03
или использовать xs:

# perl -MBenchmark=timethese -MList::Util=sum -e 'my @a = 0..1023; timethese ($ARGV[0], { XS => sub { return sum @a }, Perl => sub { my $a = 0; $a += $_ foreach (@a); return $a } } )' 1000000
Benchmark: timing 1000000 iterations of Perl, XS...
      Perl: 129 wallclock secs (109.62 usr +  0.00 sys = 109.62 CPU) @ 9122.42/s (n=1000000)
        XS:  7 wallclock secs ( 6.05 usr +  0.00 sys =  6.05 CPU) @ 165289.26/s (n=1000000)
#

ускорение в 18 раз

Автор: MakTpaxep 14.6.2011, 10:39
Всем спасибо! Перевариваю

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)