4

Я не понимаю результатов простого теста производительности, который я запустил с использованием двух основных сценариев (работающих на высокопроизводительном сервере):

perfVar.zsh :

#!/bin/zsh -f

MYVAR=`cat $1`
for i in {1..10}
do
  echo $MYVAR
done

perfCat.zsh

#!/bin/zsh -f

for i in {1..10}
do
cat $1
done

Результат теста производительности:

> time ./perfVar.zsh BigTextFile > /dev/null
./perfVar.zsh FE > /dev/null  6.86s user 0.32s system 100% cpu 7.177 total
> time ./perfCat.zsh BigTextFile > /dev/null
./perfCat.zsh FE > /dev/null  0.01s user 0.10s system 91% cpu 0.118 total

Я бы подумал, что доступ к VARIABLE был намного быстрее, чем чтение ФАЙЛА в файловой системе ... Почему этот результат? Есть ли способ оптимизировать сценарий perfCat.zsh, уменьшив количество обращений к файловой системе?

3 ответа3

2

В bash и csh выбор переменных ...

#!/usr/bin/env bash
MYVAR=`cat $1`

#!/usr/bin/env tcsh
set myvar=`cat $1`

... заставит его выполнить команду cat а также любую интерпретацию текста, которая может произойти. Например, если переменная окружения LANG установлена в UTF8 или если она переводит символы новой строки в пробелы. Наконец, ему нужно выделить место для хранения результата cat .

Сценарий № 2, напротив, просто присваивает файл и завершает его. Фактически, поскольку он записывает в /dev/null , это, вероятно, также улучшит производительность.

Попробуйте записать в файл вместо /dev/null и обновите его. Это почти наверняка будет быстрее, но время может быть больше в соответствии друг с другом.

Наконец, имейте время только цикл вместо того, чтобы синхронизировать весь сценарий. Если вам нужно время чтения из переменной -vs- чтения из файла, то вы не синхронизируете его должным образом.

редактировать

Для синхронизации вместо использования команды time я бы порекомендовал сделать это:

#!/usr/bin/env bash

# do some stuff
date --rfc-3339=ns
for (( i = 0; i < 10; i++ )); do
  # Some more stuff
done;
date --rfc-3339=ns

Это выведет текущую дату и время с точностью до наносекунды.

1

Мне удалось воспроизвести такое же поведение в Bash. Основная проблема здесь заключается в том, что вы используете переменные оболочки таким образом, для чего они не были предназначены; и поэтому не оптимизирован для. Когда вы делаете 'echo $ HUGEVAR', оболочка должна создать командную строку, содержащую все содержимое $ HUGEVAR (даже если 'echo' является встроенной командой, командная строка все еще есть).

Таким образом, оболочка расширяет HUGEVAR в большую строку, которая затем анализируется снова, чтобы разбить ее на пустое пространство в список отдельных аргументов команды echo. (Обратите внимание, что это приведет к объединению последовательных пробельных символов во входном файле в одиночные пробельные символы). Понятно, что этот процесс не очень эффективен с большими строками.

Вы должны просто использовать метод 'cat bigfile' несколько раз; и позволить кешу файловой системы ОС выполнять свою работу и ускорить повторный доступ к большому файлу; вы избегаете тонкого (возможно, нежелательного) изменения строки, которое выполняет оболочка при использовании echo (плюс метод 'cat' будет работать с двоичными файлами, где метод оболочки может быть поврежден на двоичных данных).

0

Назначение переменных (в отличие от большинства других встроенных скриптов) - дорогостоящая операция. Причина, по которой вы видите такую резкую разницу в производительности, заключается в том, что размер данных, с которыми вы работаете. На первый взгляд это выглядит так, как будто вы назначаете данные только один раз одной переменной (MYVAR), но в действительности zsh назначает данные временному местоположению (отображение и отображение памяти) при каждом вызове echo. Обычно это не проблема, но при работе с большим объемом данных это становится заметным.

Причина, по которой кошачья петля лучше, - в два раза. Размер данных и кеширование файловой системы.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .