определение оптимального размера буфера для чтения файла в Linux - PullRequest
0 голосов
/ 04 мая 2018

Я пишу программу на C, которая читает из стандартного ввода и пишет в стандартный вывод. Но он буферизует данные так, что запись выполняется только после того, как он читает определенное количество байтов (= SIZE)

#include<stdio.h>
#include<stdlib.h>

#define SIZE 100

int main()
{
        char buf[SIZE];
        int n=0;
        //printf("Block size = %d\n", BUFSIZ);

        while( ( n = read(0, buf, sizeof(buf)) ) > 0 )
                write(1, buf, n);
        exit(0);
}

Я запускаю эту программу на Ubuntu 18.04, размещенной в Oracle Virtual Box (4 ГБ ОЗУ, 2 ядра), и тестирую программу на различные значения размера буфера. Я перенаправил стандартный ввод из файла (который содержит случайные числа, создаваемые динамически) и стандартный вывод для перехода в / dev / null. Вот сценарий оболочки, используемый для запуска теста:

#!/bin/bash

# $1 - step size  (bytes)
# $2 - start size (bytes)
# $3 - stop size (bytes)

echo "Changing buffer size from $2 to $3 in steps of $1, and measuring time for copying."

buff_size=$2

echo "Test Data" >testData
echo "Step Size:(doubles from previous size) Start Size:$2 Stop Size:$3" >>testData

while [ $buff_size -le $3 ]
do
        echo "" >>testData
        echo -n "$buff_size," >>testData
        gcc -DSIZE=$buff_size copy.c    # Compile the program for cat, with new buffer size
        dd bs=1000 count=1000000 </dev/urandom >testFile        #Create testFile with random data of 1GB        
        (/usr/bin/time -f "\t%U, \t%S," ./a.out <testFile 1>/dev/null) 2>>testData
        buff_size=$(($buff_size * 2))
        rm -f a.out
        rm -f testFile
done

Я измеряю время, затрачиваемое на выполнение программы, и записываю ее в таблицу. Тестовый запуск выдает следующие данные:

Test Data
Step Size:(doubles from previous size) Start Size:1 Stop Size:524288

1,      5.94,   17.81,

2,      5.53,   18.37,

4,      5.35,   18.37,

8,      5.58,   18.78,

16,     5.45,   18.96,

32,     5.96,   19.81,

64,     5.60,   18.64,

128,    5.62,   17.94,

256,    5.37,   18.33,

512,    5.70,   18.45,

1024,   5.43,   17.45,

2048,   5.22,   17.95,

4096,   5.57,   18.14,

8192,   5.88,   17.39,

16384,  5.39,   18.64,

32768,  5.27,   17.78,

65536,  5.22,   17.77,

131072, 5.52,   17.70,

262144, 5.60,   17.40,

524288, 5.96,   17.99,

Я не вижу каких-либо существенных изменений в времени пользователя и системы, поскольку мы используем другой размер блока. Но теоретически, когда размер блока становится меньше, генерируется много системных вызовов для одного и того же размера файла, и выполнение должно занять больше времени. Я видел результаты теста в книге Ричарда Стивенса «Расширенное программирование в среде Unix» для аналогичного теста, которая показывает, что время пользователя и системы значительно сокращается, если размер буфера, используемого в копии, близок к размеру блока. (В моем случае, размер блока составляет 4096 байт в разделе ext4)

Почему я не могу воспроизвести эти результаты? Я пропускаю некоторые факторы в этих тестах?

1 Ответ

0 голосов
/ 07 мая 2018

Вы не отключили строку #define SIZE 100 в своем исходном коде, поэтому определение через опцию (-DSIZE=1000) имеет влияние только выше этого #define. На моем компиляторе я получаю предупреждение (<command-line>:0:0: note: this is the location of the previous definition) во время компиляции.

Если вы закомментируете #define, вы сможете исправить эту ошибку.

Еще один аспект, который приходит на ум:

Если вы создадите файл на машине и сразу же прочитаете его, он будет находиться в кеше диска ОС (который достаточно велик для хранения всего этого файла), поэтому фактический размер блока диска не будет иметь большое влияние здесь.

Книга Стивенса была написана в 1992 году, когда оперативная память была намного дороже, чем сегодня, поэтому, возможно, некоторая информация там устарела. Я также сомневаюсь, что в новых изданиях книги такие вещи исчезли, потому что в целом они все еще верны.

...