Команда 'pwd' занимает много времени после загрузки большого файла (например, 40M) - PullRequest
0 голосов
/ 01 июля 2019

Следующий тестовый код теста оболочки: centOS 7 с оболочкой bash;Код содержит три фразы;фраза 1, вызов команды pwd;фраза 2, прочитайте большой файл (cat the file);Фраза 3, сделайте то же самое, что и фраза 1;

Стоимость фразы 3 намного больше, чем фраза 1 (например, 21 с против 7 с)

Но на платформе MacOS затраты временифразы 1 и фразы 3 равны.#! / bin / bash

#phrase 1
timeStart1=$(date +%s)
for ((ip=1;ip<=10000;ip++));
do
nc_result=$(pwd)
done
timeEnd1=$(date +%s)
timeDelta=$((timeEnd1-timeStart1))

echo $timeDelta

#phrase 2
fileName='./content.txt'   #one big file,eg. a 39M file
content=`cat $fileName`

#phrase 3
timeStart2=$(date +%s)
for ((ip=1;ip<=10000;ip++));
do
nc_result=$(pwd)
done
timeEnd2=$(date +%s)
timeDelta2=$((timeEnd2-timeStart2))
echo $timeDelta2

Ответы [ 2 ]

1 голос
/ 01 июля 2019

Ответ Славомира содержит ключевую часть проблемы, но без полного объяснения. Ответ на Что означает, что 'fork ()' скопирует адресное пространство исходного процесса? в Unix & Linux StackExchange имеет хороший фон.

Подстановка команд - $(...) - реализуется путем fork() извлечения отдельной копии вашей оболочки, в которой выполняется команда - в данном случае pwd -.

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

Тем не менее, по-прежнему стоит настроить страницы, настроенные для копирования в новую физическую память при их изменении! Некоторые платформы, такие как Cygwin, имеют худшие / более дорогие реализации fork; некоторые (очевидно MacOS?) имеют более быстрые; эта разница - то, что вы измеряете здесь.


Два выноса:

  • Это не pwd, это медленно, это $( ). Это будет так же медленно с $(true) или любой другой встроенной оболочкой, и значительно медленнее с любой не встроенной командой.

  • Ни в коем случае не используйте $(pwd) - нет никакой причины платить эту цену за разделение дочернего процесса для измерения его рабочего каталога, когда вы можете просто запросить у родительской оболочки свой рабочий каталог напрямую используя nc_result=$PWD.

0 голосов
/ 01 июля 2019

$ () вызывает подоболочку. Третья команда запускается при выполнении второй команды.

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