URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 8508
[ Назад ]

Исходное сообщение
"awk быстрее perl ?"

Отправлено greenwar , 11-Ноя-09 03:50 
..или это я ещё совсем зелёный?

есть задачка:
из файла:
Name: network1
Dropped packets: 15618
Dropped packets for IPv6: 27
Dropped packets: 74
Dropped packets for IPv6: 0
Failed RADIUS Authentication procedures: 0
Failed RADIUS Accounting procedures: 0
Name: network2
Dropped packets: 1117
Dropped packets for IPv6: 0
Dropped packets: 0
Dropped packets for IPv6: 0
Failed RADIUS Authentication procedures: 0
Failed RADIUS Accounting procedures: 0

сделать:
network1:15618:27:74:0:0:0
network2:1117:0:0:0:0:0

файл, соот-но, увеличить до мегов 300 (я на таком тестил) банальным размножением блоков по 7 строк..

решение на awk:
awk -F': *' ' { r = r ? r ":" $2 : $2 } /^Failed RADIUS Accounting procedures/{ print r; r = 0 } ' infile > outfile

голову грел больше 2х часов, но максимум, чего добился, это вот такого решения на perl:
#!/usr/bin/perl -w

open(FH,"infile");
open(NEW,">outfile");
while(<FH>){
    if(/: (network\d+?)$/){print NEW "\n$1";next}
    /: (\d+)$/;print NEW ":$1"
}

awk отрабатывает за 29 сек, перл за 40..
как оптимизировать код на perl до такого уровня?


Содержание

Сообщения в этом обсуждении
"awk быстрее perl ?"
Отправлено ACCA , 11-Ноя-09 07:27 
>..или это я ещё совсем зелёный?

Кокетничаешь. Можно выжать разве что ещё пяток процентов по мелочи типа


#!/usr/bin/perl -w

while(<>){
    if(/: (network\d+)/){print "\n$1";next}
    /: (\d+)/;print ":$1"
}

- нет $ в конце regexp и \d+ вместо \d+?.

А вот времена на 400M файле совсем даже обратные:


$ time ./counter.pl datafile.txt > /dev/null

real    0m26.809s
user    0m26.510s
sys    0m0.290s

$ time awk -F': *' ' { r = r ? r ":" $2 : $2 } /^Failed RADIUS Accounting procedures/{ print r; r = 0 }' datafile.txt > /dev/null

real    0m54.194s
user    0m53.950s
sys    0m0.240s

$ uname -a
Linux hostname 2.6.31-14-generic #48-Ubuntu SMP Fri Oct 16 14:05:01 UTC 2009 x86_64 GNU/Linux
$ awk --version
GNU Awk 3.1.6
$ perl --version
This is perl, v5.10.0 built for x86_64-linux-gnu-thread-multi


Если время обработки настолько критично, я бы не постеснялся написать на C.


"awk быстрее perl ?"
Отправлено greenwar , 11-Ноя-09 10:19 
>Кокетничаешь.

та не.. месяц назад я о перле знал ровно 0

>- нет $ в конце regexp и \d+ вместо \d+?.

а вот зря их там нет.. на моей машине это увеличивает время на 3 секунды
из книжки запомнил, что унарные + * сами по себе жадные, ищут максимальную длину, а с ? ищут минимальную. при $ должен искать с конца строки, а не с начала
вообщем, регулярке так зона поиска сужается похоже раза в 2

>А вот времена на 400M файле совсем даже обратные:

хмхм.. значит, перл у меня не оптимизирован на производительность и ядро тоже
+целерон на буке стоит, а не SMP

>Если время обработки настолько критично, я бы не постеснялся написать на C.

та не, просто удивился, что перл, как и авк, написан на си, заточен под обработку текста, как никто, а при этом сливает


"awk быстрее perl ?"
Отправлено svn , 11-Ноя-09 11:33 
>та не, просто удивился, что перл, как и авк, написан на си,
>заточен под обработку текста, как никто, а при этом сливает

У них разные регулярные выражения. В awk более быстрые основанные на конечных автоматах, в perl более функциональные.

PS: Парсер на С (flex) обойдёт их в десятки раз ))


"awk быстрее perl ?"
Отправлено Pahanivo , 11-Ноя-09 14:03 
>>та не, просто удивился, что перл, как и авк, написан на си,
>>заточен под обработку текста, как никто, а при этом сливает
>
>У них разные регулярные выражения. В awk более быстрые основанные на конечных
>автоматах, в perl более функциональные.
>
>PS: Парсер на С (flex) обойдёт их в десятки раз ))

а в шаблонном файле не быстрее подстроку сравнить чем regex заюзать?


"awk быстрее perl ?"
Отправлено Vladin , 14-Ноя-09 22:52 
+1
перл быстрее
у меня время на 300М файле по этим скриптам
awk: 1 мин 40 сек
perl: 29 сек

вариант без регулярок: 22 сек

open(FH,"infile");
open(NEW,">outfile");
while(<FH>){
  chop;
  $_  = substr( $_, index($_,':')+2 );
  if( ord($_) == 110 ) {
    print NEW "\n$_";
    next;
  }
  print NEW ":$_";
}


"awk быстрее perl ?"
Отправлено greenwar , 15-Ноя-09 15:26 
>[оверквотинг удален]
>open(NEW,">outfile");
>while(<FH>){
>  chop;
>  $_  = substr( $_, index($_,':')+2 );
>  if( ord($_) == 110 ) {
>    print NEW "\n$_";
>    next;
>  }
>  print NEW ":$_";
>}

чё-то ляпов многовато..

>  chop;

плохая привычка чопать конец строки, можно чопнуть чего-нить нужное
лучше чомпать (chomp)

>  $_  = substr( $_, index($_,':')+2 );

а где гарантия, что будет именно 2 символа в конце строки? даже в примере есть далеко не 2

так и регуляркой можно было строгать треть строк мимо.. было бы быстрее :)
к тому же, вы несложную регулярку на 3 функции заменили.. шило на мыло имхо

>  if( ord($_) == 110 ) {

регуляркой это: /: \D+$/


"awk быстрее perl ?"
Отправлено Vladin , 15-Ноя-09 16:48 
>>  chop;
>
>плохая привычка чопать конец строки, можно чопнуть чего-нить нужное
>лучше чомпать (chomp)

согласен, изначально был chomp, в ходе эксперимента заменил на chop, выиграл 1 сек

>>  $_  = substr( $_, index($_,':')+2 );
>
>а где гарантия, что будет именно 2 символа в конце строки? даже
>в примере есть далеко не 2

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

>так и регуляркой можно было строгать треть строк мимо.. было бы быстрее
>:)
>к тому же, вы несложную регулярку на 3 функции заменили.. шило на
>мыло имхо

7 сек из 29 = 24%, далеко не шило
в регулярке больше работает комп, в моем случае - программист

>>  if( ord($_) == 110 ) {
>
>регуляркой это: /: \D+$/

нет, это проверка что первый символ в строке равен 'n'
взято из идеологии си, там строка является массивом и работает конструкция string[0] == 'n'


"awk быстрее perl ?"
Отправлено greenwar , 16-Ноя-09 12:09 
>согласен, изначально был chomp, в ходе эксперимента заменил на chop, выиграл 1
>сек

странно.. по идее работают по одному принципу

>>>  $_  = substr( $_, index($_,':')+2 );
>>
>>а где гарантия, что будет именно 2 символа в конце строки? даже
>>в примере есть далеко не 2
>
>тут не то, ищем где стоит дветочие и отрезаем его и пробел
>за ним
>т.е. убираем название параметра, оставляя только значение

а index и регекспы разными механизмами находят двоеточие в строке?

>>так и регуляркой можно было строгать треть строк мимо.. было бы быстрее
>>:)
>>к тому же, вы несложную регулярку на 3 функции заменили.. шило на
>>мыло имхо
>
>7 сек из 29 = 24%, далеко не шило
>в регулярке больше работает комп, в моем случае - программист

хорошо, если так, но пока не ясно, откуда такая большая разница между index и регекспом. ищут одно и тоже, а механизмы настолько разные?
полезная тема для познания дао оптимизации

>>>  if( ord($_) == 110 ) {
>>
>>регуляркой это: /: \D+$/
>
>нет, это проверка что первый символ в строке равен 'n'
>взято из идеологии си, там строка является массивом и работает конструкция string[0]
>== 'n'

нутк /: \D+$/ означает любое НЕ число после двоеточия. если он встретит там туже букву 'n', сработает if


"awk быстрее perl ?"
Отправлено greenwar , 29-Май-10 11:25 
тэкс, тут появилась ещё одна непонятка.. теперь PHP быстрее Perl на регулярках ^^
поможете разобраться в причинах?

<?php
$fp = fopen('text.txt', 'rt');
while (!feof($fp)) {
  $str = fgets($fp);
  for($i=0; $i<100; $i++) {
    $pattern_str = rand(100, 1000);
    preg_match_all('/'.$pattern_str.'/', $str, $out);
  }
}
?>

в 3 раза быстрее, чем:

#!/usr/bin/perl -w

while(<>){ # обрабатываем построчно указанный файл. формат запуска скрипта: time ./script textfile

    for(0..99){ # цикл на 10к раз. в каждой строке 10000 раз ищем рандомное число от 100 до 1000
        $searchline=(int rand(901)+100); # строка для поиска: рандомное целое число от 100 до 1000
        $_=~/$searchline/g; # ищем регекспом с продолжением поиска по строке после 1го совпадения
    }
}

в качестве файла берётся обычный 20-меговый архив или бинарник или текстовик