Perl:написать тайну скорости?

Как скорость вывода может быть выше, чем скорость записи на жесткий диск?

обновление 1: Я изменил следующее:

  1. выключил антивирус. Никакое изменение.

  2. вставлен новый физический диск и используется первый раздел для испытания. (Диск для первоначального теста на последний раздел, отдельный от системного раздела, но на том же физическом диске.). Результат: есть то же самое циклическая картина, но система больше не не отвечает в ходе проверки. Скорость записи несколько выше (может быть, из-за использования первого разделение и / или отсутствие помех системе раздел.) Предварительный вывод: был какой-то помех от системного раздела.

  3. установлен 64 бит Perl. Циклы ушли и все стабильно на 2-секундной шкале времени: 55% CPU on одиночный сердечник, пишет скорость около 65 MB / s.

  4. пробовал на оригинальном диске с 64-битным Perl. Результат: где-то посередине. Циклы 8 секунд, процессор 20-50%, 35 - 65 МБ/сек (вместо глубокого цикла 0-100%, 0 - 120 МБ/сек). Система лишь слегка не реагирует. Скорость записи составляет 50 МБ / сек. Это подтверждает теорию интерференции.

  5. промывка в скрипте Perl. Еще не пробовал.


хорошо, я прошел мимо первый шаг. Я написан на Perl скрипт, который может генерировать очень большой текстовый файл (например, 20 ГБ) и по сути, это всего лишь ряд:

print NUMBERS_OUTFILE $line;

где $line-длинная строка с "n " в конце.

при запуске скрипта Perl скорость записи составляет около 120 МБ/с (согласовано между тем, что вычисляется скриптом, Процесс Explorer и "IO пишет байты / sec" для процесса Perl в мониторе производительности.) и 100% CPU на одном ядре бежит дальше. Эта ставка, I верю, выше, чем пишу скорость жесткого диска.

затем через некоторое время (например, 20 секунд и 2.7 GB написано) вся система становится очень невосприимчивой, и CPU падает до 0%. Это длится, например, 30 секунд. Средняя скорость записи над этими 2 участками последователен с скоростью записи жесткий диск. Времена и размеры, упомянутые в этом пунктом варьируется от запуска к запуску. Диапазон 1 ГБ до 4.3 GB для первого этапа наблюдалось до сих пор. Вот это стенограмма для запуска с 4.3 GB.

существует несколько из этих циклов для текстового файла 9.2 GB генерируется в тесте:

Enter image description here

что происходит?


полное Perl script и скрипт драйвера BAT (HTML отформатирован с pre tag). Если две переменные среды MBSIZE и OUTFILE настроены, тогда скрипт Perl должен иметь возможность запускать без изменений на других платформах, чем Окна.

платформа: Perl 5.10.0 от ActiveState; (первоначально 32 бит, позже 64 бит); построить 1004. Windows XP x64 SP2, нет файла страницы, 8 ГБ оперативной памяти, четырехъядерный процессор AMD, 500 ГБ зеленых жестких дисков икры (скорость записи 85 МБ/с?).

4 ответов


Я со всеми, кто говорит, что проблема заключается в заполнении буферов, а затем в их опустошении. Попробуйте включить автосброс чтобы избежать наличия буфера (в Perl):

#!/usr/bin/perl

use strict;
use warnings;

use IO::Handle;

my $filename = "output.txt";

open my $numbers_outfile, ">", $filename
    or die "could not open $filename: $!";

$numbers_outfile->autoflush(1);

#each time through the loop should be 1 gig
for (1 .. 20) {
    #each time though the loop should be 1 meg
    for (1 .. 1024) {
        #print 1 meg of Zs
        print {$numbers_outfile} "Z" x (1024*1024)
    }
}

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


все данные кэшируются в буферах перед эффективной укладкой на физический диск. Буфер из системы, другой внутри самого диска (вероятно, буфер 32MB). Пока вы заполняете эти буферы, ваша программа работает на полной скорости и 100% CPU. Как только буферы заполнены, ваша программа ждет диска, который намного медленнее, чем память и буферы, и это ожидание заставляет вас прекратить потреблять весь этот процессор.

возможно, вы можете сделать свой код "ждать диска" из начните, используя некоторый Perl, эквивалентный fflush().


возможно, ОС записывает на диск так быстро, как может (85 Мб/с), и помещает лишние 35 МБ/с в буфер, и когда он заполняется, приостанавливает приложение, чтобы очистить буфер. Поскольку буфер сливается со скоростью 85 Мб / с, вы ожидаете, что он займет 35/85 = ~0,4 раза больше времени для слива, чем для заполнения. Это в целом совместимо с вашим графиком, если я достаточно прищурюсь.

вы можете оценить размер буфера как произведение времени паузы и скорости диска.


посмотрите на график! Зеленая линия указывает среднюю длину очереди диска. В какой-то момент он получает пик, а затем процессор переходит в 0. IO пишет также идет в 0. Он возвращается к норме, пока не будет показан второй пик. Затем CPU и IO пишут возврат к нормальному. Затем и IO и CPU снова падают, чтобы снова подняться на следующий пик очереди. И снова вниз, и снова вверх...

возможно, в этот момент диск выполняет физическую запись. Однако также может оказаться, что в этот момент система выполняет проверку диска, считывая данные, которые она только что написала, чтобы проверить записи, убедившись, что данные записаны правильно.

еще одна вещь, которую я замечаю, - это размер 2.7 GB. Поскольку вы запускаете это в системе Windows, я становлюсь немного подозрительным, так как это касается объема памяти, который может обрабатывать Windows, как 32-битный процесс. 64-битные окна обеспечат приложение до 3 ГБ ОЗУ (немного меньше), но затем ему нужно снова выпустить его. Вы можете хотите использовать Process Explorer для проверки количества используемой ОЗУ и количества считываний ввода-вывода.

и, возможно, использовать 64-битную версию Perl...