Почему хвостовой файл | tr (конвейер) быстрее, чем sed или perl с большим количеством строк?

Размонтируйте смонтированные файловые системы. Корневая файловая система — это особый случай; для этого вы можете использовать mount / -o remount,ro. В Linux umount /также работает, поскольку эффективно преобразуется в предыдущую команду.


Тем не менее, вам не нужно слишком много беспокоиться о размонтировании, если только

  1. Вы смонтировали старую файловую систему, такую ​​как FAT -, используемую системным разделом EFI -или ext2, в которой не реализовано ведение журнала или что-то подобное. В современной файловой системе syncдолжно быть достаточно, и файловая система очень быстро восстановится при следующей загрузке.
  2. Возможно, вы оставили работающий процесс, выполняющий запись в файловую систему, и намеревались корректно завершить его работу. В этом случае полезно попытаться размонтировать файловые системы, потому что размонтирование завершится ошибкой и покажет ошибку занятости, чтобы напомнить вам об оставшемся модуле записи.

Вышеизложенное является важной частью. После этого вы также можете удобно отключить аппаратное обеспечение с помощью poweroff -f. Или перезагрузитесь с помощью reboot -f.

Существуетsystemd-конкретный эквивалентpoweroff -f:systemctl poweroff -f -f. Однако poweroff -fделает то же самое, и systemdподдерживает эту команду, даже если она была собрана без совместимости с SysV.


Технически,Я помню, что мой жесткий диск USB был задокументирован как требующий «безопасного удаления» Windows или эквивалентного. Но это требование не является безопасным при сбое питания, и Linux в любом случае не выполняет этого во время нормального завершения работы. Это лучше интерпретировать как означающее, что вы не должны толкать жесткий диск во время его вращения -, в том числе пытаясь отключить его. Полное отключение питания должно остановить вращение диска. Возможно, вы услышите, почувствуете или увидите, не прекратится ли оно :-).

9
21.05.2020, 21:48
4 ответа

Все сводится к объему выполняемой работы.

Ваша команда tail | trзавершается следующим:

  • вtail:
    • читать до новой строки;
    • выводить все оставшееся, не заботясь о новых строках;
  • в tr, прочитайте, не заботясь о новых строках, и выведите все, кроме «»» (фиксированного символа ).

Ваша команда sedпосле интерпретации данного скрипта делает следующее::

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

Ваша команда Perl делает следующее:после интерпретации данного скрипта:

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

Поиск новых строк оказывается дорогим для больших входных данных.

12
18.03.2021, 23:33

хвост _строки ()из tail.c:

      /* Use file_lines only if FD refers to a regular file for
         which lseek (... SEEK_END) works.  */

      if ( ! presume_input_pipe
           && S_ISREG (stats.st_mode)
           && (start_pos = lseek (fd, 0, SEEK_CUR)) != -1
           && start_pos < (end_pos = lseek (fd, 0, SEEK_END)))

Здесь end_pos = lseek (fd, 0, SEEK_END)содержимое файла пропускается. В файле _строк ()выполняется сканирование в обратном направлении с подсчетом новых строк.

lseek ()— довольно простой системный вызов для изменения смещения файла для чтения/записи.


О, кажется, я упустил тонкость в этом вопросе; )Все дело в чтении построчно, а не поблочно. Обычно хорошей идеей является объединение нескольких проходов в один сложный проход. Но здесь алгоритму нужна только самая первая новая строка.

Perl-скрипт Оле, состоящий из двух частей -и sysread(), показывает, как он переключается с поиска первой новой строки (с )на чтение максимального блока.

Когда tailработает в обратном порядке, он считывает последний блок и подсчитывает символы новой строки. Он печатает оттуда или читает в следующем блоке от -до -.

1
18.03.2021, 23:33

Мне кажется, вы хотели бы использовать perl, но это слишком медленно.

perl— это общий инструмент, и он не будет таким быстрым, как специализированный инструмент, такой как tr. Впрочем, можно подобраться:

$ tail -n +2 file.txt | tr -d \" >/dev/null;
real    0m0.040s
user    0m0.030s
sys     0m0.032s

$ perl -e 'while(sysread(STDIN,$b,1)) {$b eq "\n" and last}
           while(sysread(STDIN,$b,131072)) {
             $b=~tr/\"//d; print $b
           }' < file.txt > /dev/null;
real    0m0.049s
user    0m0.045s
sys     0m0.004s

Вы можете избежать tailи двигаться еще быстрее:

$ time (read; tr -d \") < file.txt >/dev/null
real    0m0.033s
user    0m0.021s
sys     0m0.012s
1
18.03.2021, 23:33

Главным образом потому, что perl и sed обрабатывают каждую строку отдельно.

Если вы позволите Perl обрабатывать ввод более крупными блоками и немного упростите его (см. примечание ), вы сможете сделать его намного быстрее --, но нигде так быстро, как tr:

time perl -ne ' { s/"//g; print if $. > 1 }' file.txt 1> /dev/null

real    0m0.617s
user    0m0.612s
sys     0m0.005s

time perl -pe 'BEGIN{<>;$/=\40960} s/"//g' file.txt >/dev/null

real    0m0.186s
user    0m0.177s
sys     0m0.009s

time tail -n +2 file.txt | tr -d \" 1> /dev/null

real    0m0.033s
user    0m0.031s
sys     0m0.023s

примечание :не используйте perl -ne '... if $. > 1'или awk 'NR == 1 {... } /foo/ {... }'.

Вместо этого используйте BEGIN{<>}и BEGIN{getline}.

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

7
18.03.2021, 23:33

Теги

Похожие вопросы