Почему выполняет итерации по файлу вдвое быстрее, чем чтение его в память и вычисления дважды?

  1. Если каталог не имеет Разрешения Чтения, соответствующих пользователей wont'be способным получить список файлов в нем, и, поэтому, получает доступ к нему.
  2. Можно использовать ACLs (man setfacl)
26
29.04.2014, 06:23
5 ответов
[118063]С одной стороны, первый метод вызывает [118527]tail[118528] дважды, поэтому он должен сделать больше работы, чем второй метод, который делает это только один раз. С другой стороны, второй метод должен скопировать данные в оболочку и затем отступить, поэтому он должен выполнить больше работы, чем первый метод, в котором [118529] хвост [118530] напрямую соединен с [118531] grep [118532]. Первый метод имеет дополнительное преимущество на многопроцессорной машине: [118533] grep[118534] может работать параллельно с [118535] tail[118536], в то время как второй метод строго сериализован, сначала [118537] tail[118538], затем [118539] grep[118540].

Поэтому нет очевидной причины, почему один из них должен быть быстрее другого.

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

В методе 1 основные стадии:

tail[119218] читает и ищет свою отправную точку.

tail[119220] записывает 4096-байтные куски, которые [119221]grep[119222] читает так же быстро, как и они произведены.

smb://username:password@192.168.0.1/ *or whatever your volume's IP is.*

Повторите предыдущий этап для второй строки поиска.

В методе 2 основные стадии:

  • tail[119224] читает и ищет свою отправную точку.
  • tail[119226] записывает 4096-байтовые куски, которые бэш читает 128 байт за раз, а zsh читает 4096 байт за раз.
  • Bash или zsh записывают 4096-байтовые куски, которые [119227]grep[119228] читает так же быстро, как и они произведены.
  • Повторите предыдущий шаг для второй строки поиска.
  • 128-байтовые куски Бэша при чтении вывода подстановки команды значительно замедляют его; zsh выходит примерно так же быстро, как и метод 1 для меня. Ваш пробег может варьироваться в зависимости от типа и номера процессора, конфигурации планировщика, версий используемых инструментов и размера данных.[118078].
11
27.01.2020, 19:39
[115088]На самом деле, первое решение тоже считывает файл в память! Это называется [115769] кэшированием[115770] и автоматически выполняется операционной системой.[12250] И как уже правильно объяснял [115771]mikeserv[115772], первое решение исполняет [115773] grep[12251], в то время как [115776] файл считывается, а второе выполняет его [115777] после [115778] считывания файла [115779]tail[115780].[12252] Таким образом, первое решение быстрее из-за различных оптимизаций. Но это не всегда должно быть правдой. Для действительно больших файлов, которые ОС решает не кэшировать, второе решение может стать быстрее. Но учтите, что для еще больших файлов, которые не поместятся в память, второе решение вообще не сработает[115093].
5
27.01.2020, 19:39
[116299] Я думаю, что главное отличие очень просто в том, что [116714] эхо [116715] медленное. Рассмотрим так:[12155]Как видно выше, трудоемким этапом является распечатка данных. Если вы просто перенаправитесь в новый файл и прочитаете его, то [116716]намного [116717] будет быстрее, если прочитать файл только один раз. [12156]И, как и было запрошено, со строкой здесь:[12157]Эта еще медленнее, предположительно потому, что эта строка объединяет все данные в одну длинную строку, и это замедляет grep [116718]grep[116719]:[12158]Если переменная цитируется так, чтобы не происходило разделения, то все происходит немного быстрее:[12159]Но все равно медленнее, потому что шагом ограничения скорости является печать данных.[116311].
3
27.01.2020, 19:39
.. [116131] Я тоже хотел поговорить об этом... Во-первых, я собрал файл:
  • Если вы сами запустите вышеперечисленное, вы должны придумать 1.5 миллиона строк в
    • /tmp/log
    • с соотношением 2:1 в
  • function wizard

    "успех": "правда"

    строк к

    enter image description here

    "успеху": "ложные"

    строки.

    Следующее, что я сделал, это провел несколько тестов. Я прогонял все тесты через прокси

    sh

    , так что

    время


    должно было смотреть только один процесс - и поэтому мог показать один результат для всего задания.

    Это кажется самым быстрым, даже если добавить второй файловый дескриптор и

    $ sudo su [enter]
    # dd if=/dev/random of=/dev/sda bs=512 count=1 seek=62 [enter]
    # dd if=/dev/zero of=/dev/sda bs=512 count=1 seek=62 [enter]
    

    тройник,

    repeat [times] [command]
    

    хотя я думаю, что могу объяснить почему:

    Вот твой первый:
    И твой второй:

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

    A

    here-document

    с другой стороны, для всех намерений и целей, [116522]- это файл [116909]file[116910] - дескриптор файла [116911]-

    enter image description here

    так или иначе. И как мы все знаем - Unix работает с файлами [116524].

    Самое интересное в

    here-docs

    - это то, что вы можете манипулировать их

    файловыми дескрипторами

    • - как прямым
    • |pipe[116918]-[116531] и исполнять их. Это очень удобно, так как позволяет вам немного больше свободы в указании вашего
    • |pipe

    Paste Special - 2

    , где бы вы хотели.

    enter image description here

    Мне пришлось

    тянуть

    хвост

    -


    , потому что первый

    enter image description here

    grep

    - съедает

    - здесь...doc |pipe

    и ничего не осталось для второго чтения. Но так как я

    Screenshot

    |piped

    вписал его в

    /dev/fd/3

    и поднял его снова, чтобы перейти к

    >&1 stdout,

    это не имело большого значения. Если вы используете


    grep -c


    , как многие другие рекомендуют:

    Это еще быстрее.

    Но когда я запускаю его без


    . sourcing

    tar xfj filename.tar.bz2 | 7z a -si filename.7z
    

    heredoc

    Я не могу успешно подстраховать первый процесс, чтобы запустить их полностью одновременно. Вот оно, без полной подоплеки:

    Но когда я добавляю

    и:

    cross-ref options

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

    В любом случае, причина, по которой он работает быстрее с

    echo -n "Hello World "; uptime
    

    tee

    >UnxUtils\bin\sh
    WINCOMP# echo -n "Hello "; echo World
    Hello World
    
    , заключается в том, что оба

    greps

    запускаются одновременно с одним вызовом

    sudo <your_text_editor> path/to/file
    

    хвоста. tee

    дублирует файл для нас и разделяет его на второй

    grep

    sudo chmod +x /usr/local/bin/rename.pl
    
    процесс все в потоке - все выполняется одновременно от начала до конца, так что все они тоже заканчиваются примерно в одно и то же время.

    enter image description here

    Итак, возвращаясь к первому примеру:

    И ко второму:

    Но когда мы разделяем наш вход и запускаем наши процессы одновременно:

    3
    27.01.2020, 19:39
    [115154]Я выполнил следующий тест и на моей системе полученная разница примерно в 100 раз больше для второго скрипта. [12287]Мой файл представляет собой выходной файл в формате strace, называемый [115847]bigfile[12288]Scripts[12289]У меня на самом деле нет никаких совпадений для grep, так что ничего не написано в последнем канале до [115849]wc -l[12290]Вот тайминги:[12291]Так что я снова запустил эти два скрипта с помощью команды strace[12292]Вот результаты из следов:[12293]И p2. strace[12294]Analysis[12295]Неудивительно, что в обоих случаях большая часть времени уходит на ожидание завершения процесса, но p2 ждет в 2,63 раза дольше, чем p1, и, как уже упоминали другие, вы начинаете поздно в p2.sh. [12296] Так что теперь забудьте о [115853] waitpid[115854], проигнорируйте столбец [115855] %[115856] и посмотрите на столбец секунд на обеих трассах.[12297] Самое большое время [115858] p1 проводит большую часть своего времени в чтении, вероятно, понятно, потому что есть большой файл, который нужно прочитать, но p2 тратит на чтение в 28,82 раза дольше, чем p1. - [115859]bash[115860] не ожидает чтения такого большого файла в переменную и, вероятно, читает буфер за раз, разбивается на строки, а затем получает другую.[12298]read count[115862] p2 составляет 705k против 84k для p1, каждое чтение требует переключения контекста в пространство ядра и снова выходит. Почти в 10 раз больше чтений и переключателей контекста.[12299]Время записи[115864] p2 тратит на запись в 41,93 раза больше, чем p1[12300]счетчик записи[115866] p1 делает больше записи, чем p2, 42k против 21k, однако они намного быстрее.[12301]Вероятно, из-за [115867]эхо[115868] строк в [115869]grep[115870] в отличие от буферов записи хвоста. [12302] Далее больше [115872], p2 тратит больше времени на запись, чем на чтение, p1 - наоборот! [12303] Другой фактор [115874] Посмотрите на число системных вызовов [115875]brk[115876] : p2 тратит в 2,42 раза больше времени на разрыв, чем на чтение! В p1 (он даже не регистрируется). [115877]brk[115878] - это когда программе нужно расширить адресное пространство, потому что изначально не было выделено достаточно, вероятно, это связано с тем, что bash должен был прочитать этот файл в переменную, и не ожидал, что он будет настолько большим, и, как упоминал @scai, если файл станет слишком большим, то даже это не сработает. [12304]tail[115880], вероятно, является довольно эффективным устройством для чтения файлов, потому что именно для этого он и был создан, он, вероятно, запоминает файл и сканирует его на наличие разрывов строк, что позволяет ядру оптимизировать i/o. bash не так хорош как при чтении, так и при записи.[12305]p2 тратит 44 мс и 41 мс в [115881]клоне[115882] и [115883]execv[115884] это не поддающееся измерению количество для p1. Вероятно, баш-чтение и создание переменной из хвоста.[12306]Наконец, Totals[115886] p1 выполняет ~ 150k системных вызовов против p2 740k (в 4,93 раза больше).[12307]Устраняя ожидание, p1 тратит 0,014416 секунд на выполнение системных вызовов, p2 - 0,439132 секунды (в 30 раз дольше). [12308]Получается, что p2 большую часть времени проводит в пользовательском пространстве, ничего не делая, кроме ожидания завершения системных вызовов и реорганизации памяти ядра, p1 выполняет больше записей, но более эффективен и вызывает значительно меньшую системную нагрузку, а значит, быстрее. [12309]Заключение[12310]Я бы никогда не стал беспокоиться о кодировании через память при написании бэш-скрипта, это не значит, что вы не пытаетесь быть эффективными.[12311]tail[115890] спроектирован для того, чтобы делать то, что он делает, это, вероятно, [115891]карта памяти[115892] файл так, чтобы он был эффективным для чтения и позволял кернелу оптимизировать i/o.[12312]Лучшим способом оптимизации вашей проблемы может быть сначала [115893]grep[115894] для ''успеха'': ' строк, а затем считайте правильные и неправильные, [115895]grep[115896] имеет опцию счета, которая опять же позволяет избежать [115897]wc -l[115898], или даже лучше, пропустить хвост через [115899]awk[115900] и считать правильные и неправильные одновременно. p2 не только занимает много времени, но и добавляет нагрузку в систему, пока память перетасовывается с помощью brks.[115207].
    26
    27.01.2020, 19:39

    Теги

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