..или это я ещё совсем зелёный?есть задачка:
из файла:
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 -wopen(FH,"infile");
open(NEW,">outfile");
while(<FH>){
if(/: (network\d+?)$/){print NEW "\n$1";next}
/: (\d+)$/;print NEW ":$1"
}awk отрабатывает за 29 сек, перл за 40..
как оптимизировать код на perl до такого уровня?
>..или это я ещё совсем зелёный?Кокетничаешь. Можно выжать разве что ещё пяток процентов по мелочи типа
#!/usr/bin/perl -wwhile(<>){
if(/: (network\d+)/){print "\n$1";next}
/: (\d+)/;print ":$1"
}- нет $ в конце regexp и \d+ вместо \d+?.
А вот времена на 400M файле совсем даже обратные:
$ time ./counter.pl datafile.txt > /dev/nullreal 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.
>Кокетничаешь.та не.. месяц назад я о перле знал ровно 0
>- нет $ в конце regexp и \d+ вместо \d+?.
а вот зря их там нет.. на моей машине это увеличивает время на 3 секунды
из книжки запомнил, что унарные + * сами по себе жадные, ищут максимальную длину, а с ? ищут минимальную. при $ должен искать с конца строки, а не с начала
вообщем, регулярке так зона поиска сужается похоже раза в 2>А вот времена на 400M файле совсем даже обратные:
хмхм.. значит, перл у меня не оптимизирован на производительность и ядро тоже
+целерон на буке стоит, а не SMP>Если время обработки настолько критично, я бы не постеснялся написать на C.
та не, просто удивился, что перл, как и авк, написан на си, заточен под обработку текста, как никто, а при этом сливает
>та не, просто удивился, что перл, как и авк, написан на си,
>заточен под обработку текста, как никто, а при этом сливаетУ них разные регулярные выражения. В awk более быстрые основанные на конечных автоматах, в perl более функциональные.
PS: Парсер на С (flex) обойдёт их в десятки раз ))
>>та не, просто удивился, что перл, как и авк, написан на си,
>>заточен под обработку текста, как никто, а при этом сливает
>
>У них разные регулярные выражения. В awk более быстрые основанные на конечных
>автоматах, в perl более функциональные.
>
>PS: Парсер на С (flex) обойдёт их в десятки раз ))а в шаблонном файле не быстрее подстроку сравнить чем regex заюзать?
+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 ":$_";
}
>[оверквотинг удален]
>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+$/
>> chop;
>
>плохая привычка чопать конец строки, можно чопнуть чего-нить нужное
>лучше чомпать (chomp)согласен, изначально был chomp, в ходе эксперимента заменил на chop, выиграл 1 сек
>> $_ = substr( $_, index($_,':')+2 );
>
>а где гарантия, что будет именно 2 символа в конце строки? даже
>в примере есть далеко не 2тут не то, ищем где стоит дветочие и отрезаем его и пробел за ним
т.е. убираем название параметра, оставляя только значение>так и регуляркой можно было строгать треть строк мимо.. было бы быстрее
>:)
>к тому же, вы несложную регулярку на 3 функции заменили.. шило на
>мыло имхо7 сек из 29 = 24%, далеко не шило
в регулярке больше работает комп, в моем случае - программист>> if( ord($_) == 110 ) {
>
>регуляркой это: /: \D+$/нет, это проверка что первый символ в строке равен 'n'
взято из идеологии си, там строка является массивом и работает конструкция string[0] == 'n'
>согласен, изначально был 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
тэкс, тут появилась ещё одна непонятка.. теперь 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-меговый архив или бинарник или текстовик