Как определить самый медленный компонент моего конвейера оболочки? - PullRequest
3 голосов
/ 10 октября 2011

У меня очень длинный и сложный конвейер оболочки, настроенный для захвата 2,2 ГБ данных и их обработки.В настоящее время обработка занимает 45 минут.Конвейер представляет собой набор команд cut, grep, sort, uniq, grep и awk, связанных вместе.У меня есть подозрение, что это часть grep, которая заставляет его занимать так много времени, но у меня нет возможности подтвердить это.

Есть ли способ «профилировать» весь конвейер от конца до конца, чтобы определить, какойКомпонент самый медленный, и если он связан с процессором или вводом-выводом, чтобы его можно было оптимизировать?

Я не могу опубликовать всю команду здесь, к сожалению, так как для этого потребуется опубликовать служебную информацию, но я подозреваю, что это следующий бит, проверяющий еес htop:

grep -v ^[0-9]

Ответы [ 3 ]

5 голосов
/ 10 октября 2011

Один из способов сделать это - постепенно построить конвейер, синхронизировать каждое добавление и извлечь как можно больше из уравнения (например, вывести на терминал или в файл).Очень простой пример показан ниже:

pax:~$ time ( cat bigfile >/dev/null )
real 0m4.364s
user 0m0.004s
sys  0m0.300s

pax:~$ time ( cat bigfile | tr 'a' 'b' >/dev/null )
real 0m0.446s
user 0m0.312s
sys  0m0.428s

pax:~$ time ( cat bigfile | tr 'a' 'b' | tail -1000l >/dev/null )
real 0m0.796s
user 0m0.516s
sys  0m0.688s

pax:~$ time ( cat bigfile | tr 'a' 'b' | tail -1000l | sort -u >/dev/null )
real 0m0.892s
user 0m0.556s
sys  0m0.756s

Если вы сложите приведенное выше время системы и пользователя, вы увидите, что приращения увеличиваются следующим образом:

  • 0,304 (0,004+ 0,300) секунд для cat;
  • 0,436 (0,312 + 0,428 - 0,304) секунд для tr;
  • 0,464 (0,516 + 0,688 - 0,436 - 0,304) секунд дляtail
  • 0,108 (0,556 + 0,756 - 0,464 - 0,436 - 0,304) секунд для sort.

Это говорит о том, что основные вещи, на которые нужно обратить внимание, это tailи tr.

Теперь, очевидно, это только для ЦП, и мне, вероятно, следовало бы выполнить несколько прогонов на каждом этапе для целей усреднения, но это основной первый подход, который я бы выбрал.

Если окажется, что это действительно ваш grep, есть несколько других доступных вам вариантов.Существует множество других команд, которые могут обрезать строки, начинающиеся не с цифры, но вы можете обнаружить, что пользовательская команда для этого может быть еще быстрее, псевдокод, как (не проверено, но вы должны получитьidea):

state = echo
lastchar = newline
while not end of file:
    read big chunk from file
    for every char in chunk:
        if lastchar is newline:
            if state is echo and char is non-digit:
                state = skip
            else if state is skip and and char is digit:
                state = echo
        if state is echo:
            output char
        lastchar = char

Пользовательский, целевой код, подобный этому, иногда можно сделать более эффективным, чем механизм обработки регулярных выражений общего назначения, просто потому, что его можно оптимизировать для конкретного случая.Является ли это правдой в этом случае, или любой случай в этом отношении, это то, что вы должны проверить.Моя мантра оптимизации номер один - мера, не угадай!

4 голосов
/ 10 октября 2011

Я сам нашел проблему после некоторых дальнейших экспериментов.Похоже, это связано с поддержкой кодировки в grep.Используя следующий зависший конвейер:

grep -v ^[0-9]

Я заменил его на sed следующим образом, и он закончился менее чем за 45 секунд!

sed '/^[0-9]/d'
1 голос
/ 22 октября 2011

Это просто с zsh :

zsh-4.3.12[sysadmin]% time sleep 3 | sleep 5 | sleep 2
sleep 3  0.01s user 0.03s system 1% cpu 3.182 total
sleep 5  0.01s user 0.01s system 0% cpu 5.105 total
sleep 2  0.00s user 0.05s system 2% cpu 2.121 total
...