LinuxForum.Fans
Тема

о sed и grep, а также о том как они читают, ищут и всякой ерунде

Автор: Fat-Zer 26 сообщений 5289 просмотров
14.11.2014 12:08 #400813
"drBatty" написал:
2. в принципе быстрее, т.к. прерывается как только найдёт.

grep -m 1 тоже прервётся на первом варианте... кроме того grep в принципе быстрее в абсолютных показателях (на счёт grep -P — хз)... но скорость тут не особо важна...

"drBatty" написал:
(в данном случае sed прервётся, но tar всё равно будет читать до победного. Хотя его тоже можно и остановить маской файла, и вывести посл. строку командой tail -n1).

когда умрёт grep или sed, tar тоже умрёт от SIGPIPE'а...

15.11.2014 06:02 #400915

"Fat-Zer" написал:
кроме того grep в принципе быстрее в абсолютных показателях
4.2
grep имеет свою реализацию regexp, а sed использует glibc(конечно в версии sed для Windows тоже своя).

А вот что быстрее? Я не знаю. До выхода последних версий grep она тупила по-чёрному, но недавно её всё-же довели до ума(если верить разработчикам). К тому же, разработчики grep не шибко озабочены быстродействием(что правильно), чего не скажешь о разработчках glibc(для sed быстродействие тоже не нужно, но не только в sed используются regexp'ы).

На практике, быстродействие одинаковое:

На мелких файлах оно равно нулю (программа дольше в память грузится и выгружается)
На больших файлах скорость упирается в HDD и/или RAM, а процессор простаивает.

"Fat-Zer" написал:
на счёт grep -P — не знаю
за то я знаю: перловые регулярки требуют множество возвратов, а обычные регулярки выполняются всегда за один проход.

"Fat-Zer" написал:
когда умрёт grep или sed, tar тоже умрёт от SIGPIPE'а...
не выспались? Ещё 4.2
[console]$ time ( sleep 3|echo )


real 0m3.017s
user 0m0.012s
sys 0m0.008s
[/console]
"умирание" echo не мешает sleep'у тормозить свои 3 сек.

Уж сколько раз можно объяснять, что программы выполняются параллельно.
15.11.2014 11:00 #400928
"drBatty" написал:
grep  имеет  свою реализацию regexp, а sed  использует glibc(конечно в версии sed для Windows  тоже своя).

где-то тут давно уже обсуждали это с примерами и прочими повторяться лень...
ЕМНИП там выигрыш в реальном времени за счёт того что буфер у grep'а 256к против 64к у седа... и небольшой плюс в user'е за счёт мелких ухищрений вроде того, что grep ищет не все \n.

"drBatty" написал:
На практике, быстродействие одинаковое:

нуда... разница будет только на сферическом файле в tmpfs'е...

"drBatty" написал:
"умирание" echo не мешает sleep'у тормозить  свои 3 сек.

SIGPIPE посылается при записи в обломанную трубу (stdout). т.к. sleep не пишет — ему, само собой, по барабану... а вот с кошкой, как и с tar -t, прекрасно срабатывает...

16.11.2014 02:01 #401041
"Fat-Zer" написал:
ЕМНИП там выигрыш в реальном времени за счёт того что буфер у grep'а 256к против 64к у седа...
какой именно буфер? Если вы про ввод/вывод потоков, то он не в sed, а тот самый, который в fread(3)/fwrite(3), и если он вам не нравится, то напишите
[console]sed --unbuffered[/console]
вообще никакого не будет.

Что там в grep — я не знаю. Да и вообще не понимаю, какое он к быстродействию имеет отношение.

"Fat-Zer" написал:
и небольшой плюс в user'е за счёт мелких ухищрений вроде того, что grep ищет не все \n.
sed вообще \n не ищет. Это для неё "конец записи", sed начинает работу с загрузки данных до первого \n, потом эти данные обрабатывает, потом результат выводит. Затем цикл повторяется. Это же текстовый редактор, а текст это список строк.

"Fat-Zer" написал:
разница будет только на сферическом файле в tmpfs'е...

не только. Для sed можно любой скрипт написать, и тогда разница ощутима.
К примеру:
[console]$ echo "ABCDEFG" | sed -r 's/.*/\r&\r/;:l;s/(\r.)(.*)(.\r)/\3\2\1/;tl;s/\r//g'
GFEDCBA
[/console]
(это как rev)
Да, grep такого не умеет, потому с какой скоростью оно работает — роли не играет.

"Fat-Zer" написал:
SIGPIPE посылается при записи в обломанную трубу (stdout). т.к. sleep не пишет — ему, само собой, по барабану... а вот с кошкой, как и с tar -t, прекрасно срабатывает...
а, ну да.
если юзать grep -m, то одинаково получится.
16.11.2014 02:45 #401047
"drBatty" написал:
какой именно буфер?  Если вы про ввод/вывод потоков, то он не в sed, а тот самый, который в fread(3)/fwrite(3), и если  он вам  не нравится, то напишите

а grep использует read/write (иногда mmap) и буфер в несколько раз больше... за счёт этого сильно снижается количество системных вызовов... а если read читает из tmpfs, то экономия получается реальная.

"Fat-Zer" написал:
за счёт того что буфер у grep'а 256к против 64к у седа

с размерами я тут налажал... у меня 32к и 4к соответственно.

"drBatty" написал:
sed вообще \n не ищет. Это для неё "конец записи",  sed начинает работу с  загрузки данных до первого \n,  потом  эти данные обрабатывает, потом  результат выводит. Затем цикл повторяется. Это же текстовый редактор, а текст это список строк.

гнутый grep ищет в потоке байт, а если что-то нашёл, то только тогда ищет уже начало/конец строки...

"drBatty" написал:
Да, grep  такого не умеет, потому с какой скоростью  оно  работает — роли не играет.

ну да... grep хуже потому что он grep, а не sed...

16.11.2014 04:51 #401052
"Fat-Zer" написал:
а если read читает из tmpfs, то экономия получается реальная.
да? Очень сомневаюсь, а проверять лениво.

"Fat-Zer" написал:
гнутый grep ищет в потоке байт
а гнутый sed ищет в потоке слово.

https://ru.wikipedia.org/wiki/%D0%94%D0%B2%D0%BE%D0%B8%D1%87%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BF%D0%BE%D0%B8%D1%81%D0%BA%D0%B0_%D0%BF%D0%BE%D0%B4%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B8

Т.е. поток напрямую пишется в буфер(который имеет динамический размер, и при необходимости увеличивается), и потом в этом буфере ищется последовательность размером с машинное слово. Эта оптимизация с \n в sed тоже имеется, причём уже много лет.

А вот про какой буфер вы говорите — я не понимаю. Буфер, который внутри fread(3) имеет оптимальный размер, т.к. glibc лучше его знает, чем grep.

"Fat-Zer" написал:
ну да... grep хуже потому что он grep, а не sed...

просто возможности grep ограничены исключительно поиском подстроки, а эта задача не критична по производительности. Потому производительностью grep долгое время вообще не занимались, и только в последний год зачесались. А вот для sed производительность изначально важна. Потому она там и больше.

Просто никто не grep'ает tmpfs, а вот sed может сделать над одной строкой множество действий. Потому CPU для sed может оказаться узким местом, в отличие от grep.

16.11.2014 16:45 #401142
"drBatty" написал:
да? Очень сомневаюсь, а проверять  лениво.

вот старые тесты: grep sed perl awk - что быстрее для простых выборок

"drBatty" написал:
а гнутый sed ищет в потоке слово.
"drBatty" написал:
sed начинает работу с  загрузки данных до первого \n,  потом  эти данные обрабатывает, потом  результат выводит. Затем цикл повторяется. Это же текстовый редактор, а текст это список строк.

так определись, что sed делает? загружает строку до первого /n или целиком в свой рабочий буфер...

"drBatty" написал:
Эта оптимизация с \n в sed  тоже имеется, причём уже много лет.

не представляю, как она приминима для чего-то кроме поиска выражений... т.е. она абсолютно бесполезна для всего остального, что делает «текстовый редактор»...

"drBatty" написал:
А вот про  какой буфер вы говорите — я не понимаю.

рабочий буфер в который считывает read(2)...

"drBatty" написал:
  Буфер, который  внутри fread(3) имеет  оптимальный размер, т.к. glibc лучше его  знает, чем grep.

он имеет банальный размер страницы памяти... и оптимальный он только в том плане, что меньше было бы выделять не оптимально...

"drBatty" написал:
просто  возможности grep  ограничены  исключительно поиском подстроки, а эта задача не критична  по производительности. Потому производительностью grep долгое время вообще не занимались,  и только в последний  год зачесались.

ЛПП/4.2/белены объелись?/или что там модно сейчас писать в подобных случаях/

дисковый io нивелируется и в других случаях: например многократный grep одного файла...

17.11.2014 03:54 #401210
"Fat-Zer" написал:
вот старые тесты: grep sed perl awk - что быстрее для простых выборок

1. это очень старые тесты
2. вам там намекали на LC_ALL=C (кстати, а почему вы не экспортировали данную переменную?)
3. для таких примитивных команд никто не станет использовать sed вместо grep.
4. всё равно это всё упрётся даже в SSD, не говоря уж о HDD.

"Fat-Zer" написал:
так определись, что sed делает? загружает строку до первого /n или целиком в свой рабочий буфер...
посмотрите исходник. ЕМНИП она загружает 4К или типа того в буфер не глядя на \n, а потом раскручивает RE. Я точно не помню, да и смотрел я это место лет пять назад, не знаю, как оно сейчас.

"Fat-Zer" написал:
не представляю, как она приминима для чего-то кроме поиска выражений...
ну дык sed как раз и ищет выражения. А вот "текстовый редактор" начинается когда(и если) найдёт. Для большинства строк условие(условия) не выполняется.

"Fat-Zer" написал:
рабочий буфер в который считывает read(2)...

этот рабочий буфер в версии sed образца 2007го (примерно) года составлял 50 байт, и увеличивался(удваивался) по мере необходимости. (но не уменьшался).

"Fat-Zer" написал:
он имеет банальный размер страницы памяти...
нет. Я как-то смотрел это место, у меня было 64К, хотя страница была 4К. Конечно сейчас (и/или в другом дистрибутиве) может быть иначе.

"Fat-Zer" написал:
и оптимальный он только в том плане, что меньше было бы выделять не оптимально...

а "больше" было-бы оптимально? Если всё равно копировать надо куда-то.

"Fat-Zer" написал:
дисковый io нивелируется и в других случаях: например многократный grep одного файла...
дисковый io не нивелируется. Как раз наоборот: дисковый io занимает ВСЁ время работы, т.е. пока с диска читаются данные, sed/grep их успевает обработать намного быстрее. В итоге, мы имеем скорость как при обычном копировании(только загрузка CPU не 0.1%, а 0.2%).
17.11.2014 05:17 #401212
"drBatty" написал:
2. вам там намекали на LC_ALL=C (кстати, а почему  вы не экспортировали данную  переменную?)

это, действительно, _очень_ старые тесты...

"drBatty" написал:
этот рабочий буфер  в версии sed образца 2007го  (примерно) года  составлял  50 байт, и увеличивался(удваивался) по  мере необходимости. (но не уменьшался).

это уже куда помещается строка для того, чтобы над ней магию творить...

"drBatty" написал:
ну дык sed как  раз и ищет выражения.  А вот "текстовый редактор" начинается когда(и если) найдёт. Для большинства  строк условие(условия) не выполняется.

поверю на слово...

"drBatty" написал:
а "больше"  было-бы  оптимально?  Если всё равно копировать надо куда-то.

оптимальней c точки зрения кол-ва вызовов read(2)... ИМХО это может и даёт разницу в скорости...

"drBatty" написал:
дисковый io не нивелируется. Как раз наоборот: дисковый io занимает ВСЁ  время  работы,  т.е. пока с диска  читаются данные,  sed/grep их успевает обработать  намного  быстрее. В итоге, мы имеем  скорость как  при обычном копировании(только загрузка CPU не  0.1%, а 0.2%).

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

17.11.2014 05:42 #401215

"Fat-Zer" написал:
это уже куда помещается строка для того, чтобы над ней магию творить...
ну куда-то в этот буфер. Там довольно-таки запутанный код, я в нём когда-то разобрался, но сейчас уже не помню подробностей.

"Fat-Zer" написал:
поверю на слово...
просто код sed написан исходя именно из этого соображения.

"Fat-Zer" написал:
оптимальней c точки зрения кол-ва вызовов read(2)... ИМХО это может и даёт разницу в скорости...
может и так.

"Fat-Zer" написал:
а мне бабушка рассказывала, что после первого чтения файл с большой вероятностью он останется в кеше
при чём тут это?

Ещё раз: файл читается с HDD/SSD первый раз. Его нет в кеше.

В этом случае, процесс чтения файла с носителя идёт параллельно вычислениям.

Но вычисления быстрее чтения.

Потому скорость работы НИКАК не зависит от скорости вычисления.

Ну вот вам такой пример: корабль плывёт по морю, и его курс прокладывает капитан корабля.(ну или там штурман, я не в курсе). Время плавания никак не зависит от того, с какой скоростью прокладывается курс, от скорости прокладки курса зависит только количество свободного времени капитана.

А если файл в кеше, то непонятно, зачем его второй раз грепать?

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

PS: странные результаты в вашем тесте скорее всего объясняются тем, что grep как-то смогла mmap'нуть файл, а вот все остальные утилиты файл честно копировали в свой буфер, и именно на это потратили время. А время именно обработки регулярки настолько ничтожное, что в тесте даже не заметно.
19.11.2014 19:21 · отредактировано #401700
"drBatty" написал:
при чём  тут это?
Ещё  раз:  файл  читается с HDD/SSD  первый  раз. Его нет в кеше.

восстановлю ещё раз логику беседы...

"Fat-Zer" написал:
дисковый io нивелируется и в других случаях: например многократном grep одного файла...
"drBatty" написал:
дисковый io не нивелируется. Как раз наоборот: дисковый io занимает ВСЁ  время  работы...
"Fat-Zer" написал:
а мне бабушка рассказывала, что после первого чтения файл с большой вероятностью он останется в кеше
"drBatty" написал:
при чём  тут это?
Ещё  раз:  файл  читается с HDD/SSD  первый  раз. Его нет в кеше.
"drBatty" написал:
PS: странные  результаты в вашем тесте  скорее всего объясняются тем, что grep как-то смогла mmap'нуть файл, а вот  все остальные утилиты  файл честно копировали в свой буфер, и  именно на это  потратили   время. А время именно обработки регулярки настолько ничтожное, что в тесте  даже не  заметно.

гм... хоть и сомневаюсь, но может быть...
когда-то гнутый grep по-дефолту mmap'ил файлы... не помню, почему когда это отключили... т.к. при тестировании я версий не указал, то годать об этом можно только по cvs'у гентушного дерева...

19.11.2014 20:04 #401708
"Fat-Zer" написал:
гм... хоть и сомневаюсь, но может быть...
когда-то гнутый grep по-дефолту mmap'ил файлы... не помню, почему это отключили... т.к. при тестировании я версий не указал, то годать об этом можно только по cvs'у гентушного дерева...

Прошлой зимой на форуме был активен топик Правка/поиск текста
На основе его я наговнокодил wxLua Dictionary Search
И тогда же провел небольшое сравнение wxLua Dictionary Search

Тест проводился следующий: поиск по трем словарям (100+ мбайт в сумме, самый маленький 5000+ строк, самый крупный 123000+ строк), поисковой запрос должен был игнорировать регистр. Быстрее всех искал перл, он за полсекунды находил результат. Моя быдлореализация на Lua давала результат за 4 секунды (кстати, по ссылке этого нет, но потом проверял с LuaJIT, с ней в два раза быстрей), grep давал результат за 6 секунд.

Естественно, может если сравнивать скорость grep при наличии одного входного файла, результат будет совсем другой.

И это при том, что маска у Lua и Perl предусматривала больше совпадений, чем у grep'а

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

20.11.2014 01:49 #401762

"Fat-Zer" написал:
восстановлю ещё раз логику беседы...
зачем вы постоянно переводите разговор на кеширование? Я про него тоже знаю. И кеширование AFAIK работает совершенно одинаково, что для sed, что для grep. Да и какая разница? Ведь ни кому не придёт в голову грепать кешированный файл, зачем это надо?

"xxblx" написал:
поисковой запрос должен был игнорировать регистр. Быстрее всех искал перл
это потому, что в перловке по дефолту отключено UTF-8, а в sed по дефолту включено. Если и там и там включить(или выключить), то сравняются.

Ну и конечно проблема в том, что ЕМНИП перловка "чёткий" поиск умеет, а sed только нечёткий(по регулярному выражению). Очевидно, что "чёткий" поиск будет быстрее при прочих равных.
21.11.2014 03:17 #401863
"drBatty" написал:
зачем вы  постоянно переводите разговор на кеширование?

дык, про остальное вроде договорились...

"drBatty" написал:
. Да и какая разница? Ведь ни кому не придёт  в  голову грепать кешированный файл, зачем это  надо?

бывают житейские ситуации, когда это необходимо так делают... например, поиск конкретных строк в несколькогиговом логе... а после того, как грепнул один раз и он выдал постынку, надо скормить это wc или less'у...

"xxblx" написал:
Естественно, может если сравнивать скорость grep при наличии одного входного файла, результат будет совсем другой.

это ещё почему?

"xxblx" написал:
з.ы. я не претендую на истину, просто были вот такие наблюдения, может сам что не так сделал тогда

без попытки воспроизвести результаты пока даже не возьмусь интерпретировать их...

21.11.2014 04:49 #401875

"Fat-Zer" написал:
бывают житейские ситуации
и на е бывает, и наё…
Суть в том, что что-бы там внутри sed/grep не было, файл они обрабатывают с такой скоростью, с какой этот файл с HDD/SSD читается. Т.е. скорость не имеет значения.

"Fat-Zer" написал:
поиск конкретных строк в несколькогиговом логе... а после того, как грепнул один раз и он выдал постынку
руки кривые, ибо очевидно, что вывод Over9000 строк в терминал абсолютно бесполезен. Ну да, ладно, бывает такая беда.

Оно конечно очень большая разница:
1. ждать, пока grep файл прочитает
2. ждать, пока less найдёт конец файла, который grep читает
21.11.2014 11:46 #401911
"Fat-Zer" написал:
это ещё почему?

Потому что я лично сам не проверял, а значит и утверждать не могу каким будет результат при других входных данных - таким же или другим. Ключевые слова в том предложении были "может если ...".

23.11.2014 05:18 #402061
"xxblx" написал:
Потому что я лично сам не проверял, а значит и утверждать не могу каким будет результат при других входных данных - таким же или другим. Ключевые слова в том предложении были "может если ...".

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

"drBatty" написал:
Суть в том,  что что-бы там внутри  sed/grep не было,  файл они обрабатывают с такой скоростью, с какой этот файл с HDD/SSD читается. Т.е. скорость не имеет значения.

вообще говоря, нет. не стоит забывать о случаях, когда файл уже прочитан. А в остальных 9 из 10 — да, скорость диска много меньше скорости потрахов...
да, тут ещё можно поспорить о том, что будет в случае сверхбольших/сложных регулярок или их чрезмерного количества, как в недавней теме... но это уже отдельные темы...

"drBatty" написал:
руки кривые, ибо очевидно, что вывод Over9000 строк в терминал  абсолютно бесполезен.

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

"drBatty" написал:
2. ждать, пока less найдёт  конец файла,  который grep читает

less выводит по мере поступления, а не ждёт конца...

23.11.2014 08:05 #402081

"Fat-Zer" написал:
вообще говоря, нет. не стоит забывать о случаях, когда файл уже прочитан.
ну если он закешировался, то он маленький, и врем я его обработки значения тоже не имеет. А если он в 100Гб, то конечно имеет, но такой файл в память не влезет. Как не крути.

"Fat-Zer" написал:
да, тут ещё можно поспорить о том, что будет в случае сверхбольших/сложных регулярок или их чрезмерного количества, как в недавней теме... но это уже отдельные темы...
это вотчина sed/perl, а может быть даже C/C++. Grep тут не при чём.

"Fat-Zer" написал:
less выводит по мере поступления, а не ждёт конца...
угу. Первый экран. А что-бы с less нормально работать(поиск, навигация, и всё остальное), конца надо дождаться.
23.11.2014 14:31 #402146
"drBatty" написал:
А если он в 100Гб, то конечно имеет, но такой файл в память не влезет. Как не крути.

100 гигов текста — не жизненный пример... не представляю, когда такое может возникнуть, окромя как ситуации экологической катастрофы вызванной приступным отсутствием logrotate....
а ревльно существующие массивы, критичные к объёму 1—3Гб вполне влазят в ОП... и даже бОльшие...

"drBatty" написал:
это вотчина sed/perl, а может быть даже C/C++. Grep тут не при чём.

почему это?

24.11.2014 04:27 #402243

"Fat-Zer" написал:
100 гигов текста — не жизненный пример... не представляю, когда такое может возникнуть
SQL dump?

"Fat-Zer" написал:
а ревльно существующие массивы, критичные к объёму 1—3Гб вполне влазят в ОП... и даже бОльшие...
но при чём тут "производительность"? Такие файлы грепаются мгновенно.

"Fat-Zer" написал:
почему это?
потому что grep умеет только искать и показывать найденное. В отличие от sed, которая умеет также обрабатывать текст.

Вот, ознакомьтесь с примером: https://www.linux.org.ru/forum/general/11060479#comment-11061947
[console]$ echo "aasffdjhdghneeraasdaeaashndasghs" |\
sed -r ':l;s/(.)(.*)\1/\1\2/;tl'
asfdjhgner[/console]
для Ъ: эта команда убирает из строки все повторяющиеся символы, т.е. вместо нескольких "a", получается одна "a".

Тут скорость RE критично, ибо регулярное выражение выполняется n+1 раз, где n — число повторений символов. Grep может только одно повторение найти(если сможет, я даже и не помню, работает-ли это в grep), увы.
Войдите или зарегистрируйтесь, чтобы ответить.