Здесь речь идет не об открытии файла, а о прочтении содержимого переменной, а скорее о том, чтобы создать дополнительный процесс или нет.
grep -oP '^MemFree: *\K[0-9]+' /proc/meminfoразветвляется процесс, который запускается, grepкоторый открывается /proc/meminfo(виртуальный файл, в памяти, без дискового ввода-вывода) читает его и соответствует регулярному выражению.
Самая дорогая часть в этом - это разветвление процесса и загрузка утилиты grep и ее зависимостей от библиотеки, динамическое связывание, открытие базы данных локали, десятки файлов, которые находятся на диске (но, вероятно, кешируются в памяти).
Часть о чтении /proc/meminfoнесущественна по сравнению с тем, что ядру не нужно много времени, чтобы генерировать информацию, и не grepнужно много времени, чтобы ее прочитать.
Если вы выполните strace -cэто, вы увидите, что один open()и один read()системные вызовы, используемые для чтения, /proc/meminfo- это арахис по сравнению со всем, что grepнужно для запуска ( strace -cне считая разветвления).
В:
a=$(</proc/meminfo)
В большинстве оболочек, которые поддерживают этот $(<...)оператор ksh, оболочка просто открывает файл и читает его содержимое (и удаляет завершающие символы новой строки). bashотличается и намного менее эффективен в том, что он разветвляет процесс, выполняющий это чтение, и передает данные в родительский канал по каналу. Но здесь это делается один раз, поэтому это не имеет значения.
В:
printf '%s\n' "$a" | grep '^MemFree'
Оболочка должна порождать два процесса, которые работают одновременно, но взаимодействуют друг с другом через канал. Создание этой трубы, ее разрушение, а также запись и чтение из нее имеют небольшую стоимость. Гораздо большая стоимость порождает дополнительный процесс. Планирование процессов также оказывает определенное влияние.
Вы можете обнаружить, что использование <<<оператора zsh делает его немного быстрее:
grep '^MemFree' <<< "$a"
В zsh и bash это делается путем записи содержимого $aво временный файл, что обходится дешевле, чем запуск дополнительного процесса, но, вероятно, не даст вам никакой выгоды по сравнению с получением данных сразу /proc/meminfo. Это все еще менее эффективно, чем ваш подход, который копирует /proc/meminfoна диск, так как запись временного файла выполняется на каждой итерации.
dashне поддерживает здесь-строки, но его heredocs реализованы с помощью канала, который не требует создания дополнительного процесса. В:
grep '^MemFree' << EOF
$a
EOF
Оболочка создает трубу, разветвляет процесс. Дочерний элемент выполняется grepсо своим стандартным вводом-выводом в качестве конца чтения канала, а родительский элемент записывает содержимое на другом конце канала.
Но такая обработка каналов и синхронизация процессов все еще могут быть более дорогостоящими, чем просто получение данных /proc/meminfo.
Содержание /proc/meminfoкороткое и не занимает много времени для производства. Если вы хотите сохранить некоторые циклы ЦП, вы хотите удалить дорогостоящие детали: разветвление процессов и запуск внешних команд.
Подобно:
IFS= read -rd '' meminfo < /proc/meminfo
memfree=${meminfo#*MemFree:}
memfree=${memfree%%$'\n'*}
memfree=${memfree#"${memfree%%[! ]*}"}
Избегайте, bashчье сопоставление с образцом очень неэффективно. С помощью zsh -o extendedglobвы можете сократить его до:
memfree=${${"$(</proc/meminfo)"##*MemFree: #}%%$'\n'*}
Обратите внимание, что ^это особенность во многих оболочках (Bourne, fish, rc, es и zsh, по крайней мере, с параметром extendedglob), я бы рекомендовал процитировать его. Также обратите внимание, что echoне может использоваться для вывода произвольных данных (отсюда мое использование printfвыше).