Подтвердить что ты не робот

Почему моя "кошка" с системными вызовами медленнее по сравнению с "кошкой" Linux?

Я сделал эту функцию в C, используя системные вызовы (открытые, прочитанные и записываемые), чтобы имитировать функцию "cat" в системах Linux, и она медленнее, чем реальная...

Я использую тот же размер буфера, что и реальный "кот" , и используя "strace", я думаю, что он делает столько же системных вызовов. Но выход из моей "кошки" немного медленнее, чем настоящий "кот" .

Это код, который у меня есть:

#define BUFSIZ 32768

int sysWriteBuffer(int fdout, char *buffer, ssize_t readBytes) {
    ssize_t writtenBytes = 0;

    while(writtenBytes < readBytes) {
        writtenBytes += write(fdout,
            buffer + writtenBytes, readBytes - writtenBytes);
        if(writtenBytes == -1) {
            return -1;
        }
    }

    return 0;
}

int catPrint(int fdin, int fdout) {
    char buffer[BUFSIZ];
    ssize_t readBytes;

    do {
        readBytes = read(fdin, buffer, BUFSIZ);

        if(readBytes == -1) {
            return -1;
        }

        if(sysWriteBuffer(fdout, buffer, readBytes) == -1) {
            return -1;
        }
    } while(readBytes > 0);

    return 0;
}

Я читаю из файла (который я передаю как аргумент main, я думаю, что здесь не нужен код), чем я вызываю функцию catPrint() с этим файловым дескриптором и 1 для дескриптора вывода, поэтому он печатает стандартный вывод.

Я не понимаю, почему это медленнее, потому что я использую тот же файл для тестирования и с обоими (реальный "кот" и мой) есть только один read() и один write() для всего текста. Должен ли весь текст просто отображаться на экране?

P.S: Я отметил это как домашнюю работу, хотя мой вопрос здесь (почему он медленнее) не является частью домашней работы. Мне нужно было использовать системные вызовы для создания функции типа "cat", которая выполняется. Я просто заинтригован своим кодом, который немного медленнее.

ПРОБЛЕМА, РЕШЕННАЯ С ЧРЕЗВЫЧАЙНОСТЬЮ ИЗ МЕНЯ:
Я просто решил вызвать linux original cat несколько раз в один и тот же файл, один за другим, и я просто понял, что он был медленным в то время, как я его называл, так же медленно, как и мой собственный. Я думаю, все хорошо, чем...

Извините за то, что тратил свое время, как на этих людей.

4b9b3361

Ответ 1

Ах, на основе вашего редактирования вы были укушены буфером readahead. Вы не можете протестировать две программы, которые читают файлы рядом, выполнив их один раз. Первый всегда будет медленнее, так как файл находится на диске, как только файл будет в памяти, второй будет работать быстрее, вы должны либо создать новые данные для каждого, либо запустить их, а затем запустить оба, чтобы оба они получили преимущество буфера чтения.

Ответ 2

Возможно, вы скомпилированы без оптимизации (или без высокой настройки оптимизации)?

Кроме того, ваш код будет вызывать sysWriteBuffer один раз с readBytes равным нулю - возможно, это (частично) объясняет это?

Вы также можете встроить sysWriteBuffer (либо с помощью переключателя компилятора, либо вручную).

"inlining" означает копирование тела функции на его сайт вызова, чтобы удалить накладные расходы при вызове функции. Иногда компиляторы делают это автоматически (я думаю, что -O3 разрешает эту оптимизацию в gcc). Вы также можете использовать ключевое слово inline в gcc, чтобы сообщить компилятору встроить функцию. Если вы сделаете это, ваша декларация будет выглядеть так:

static inline int sysWriteBuffer(int fdout, char *buffer, ssize_t readBytes) {
....

Ответ 3

Исследование mmap (2).

Вы будете бросать aways niceties ftell/fread, но он пропустит слой косвенности, если чтение пропускной способности действительно важно.

Ответ 4

Без сравнения исходных кодов трудно сказать. Если вы сравниваете свою кошку с кошкой GNU, помните, что вы сравниваете код, который составляет несколько часов/дней с кодом, который развивается более двадцати лет.

Возможно, вам захочется провести более полный анализ производительности, используя обе программы с разными размерами ввода, с разных устройств (RAM-диск будет хорош) и несколько раз подряд. Вы должны попытаться определить ГДЕ в своей программе медленнее.

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

Ответ 5

Сколько? Каноническая кошка похожа на

char bufr[BUFSIZ];
ssize_t len;

while((len=read(fdin, bufr, BUFSIZ)) >0)
     write(fdout, bufr, len);

который сохраняет несколько инструкций.

Ответ 6

Вы сравнили strace обоих? Вы можете попытаться использовать параметр -tt, чтобы получить синхронизацию системных вызовов.