2015-03-01 9 views
3

Я делаю некоторые бенчмаркинга (на OS X), чтобы увидеть, как использование файловой системы влияет на пропускную способность и т. Д. Я использую параллелизм с надеждой на создание фрагментации в FS.Файловая система VS Raw disk benchmarking в C

Однако, похоже, что использование FS более эффективно, чем доступ к необработанному диску. Зачем?

Вот мой код:

#include <pthread.h> 
#include <stdio.h> 
#include <fcntl.h> 
#include <unistd.h> 
#include <stdlib.h> 

#define NO_THREADS (2) 
#define PACKET_SIZE (1024 * 4) 
#define SIZE_TO_WRITE (1024 * 1024 * 1024) 

void write_buffer(void *arg) { 
    int *p_start = arg; 
    int start = *p_start; 
    char buffer[PACKET_SIZE]; 


    char path[50]; 
    sprintf(path, "file%d", start); 
    int fd = open(path, O_CREAT | O_WRONLY | O_APPEND); 

    //int fd = open("/dev/rdisk0s4", O_WRONLY); 

    if (fd < 0) { 
     fprintf(stderr, "Cound not open.\n", stderr); 
     goto end; 
    } 

    //lseek(fd, start * SIZE_TO_WRITE, SEEK_SET); 

    int current; 
    for (current = start; current < start + SIZE_TO_WRITE; current += PACKET_SIZE) { 

     int i; 
     for (i = 0; i < PACKET_SIZE; ++i) { 
      buffer[i] = i + current; 
     } 

     if (PACKET_SIZE != write(fd, buffer, PACKET_SIZE)) { 
      fprintf(stderr, "Could not write packet %d properly.", current); 
      goto close; 
     } 
    } 

    fsync(fd); 

    close: 
    close(fd); 
    end: 
    pthread_exit(0); 
} 

void flush(void) { 
    fflush(stdout); 
    fflush(stderr); 
} 

int main(void) { 
    pthread_t threads[NO_THREADS]; 
    int starts[NO_THREADS]; 
    int i; 

    atexit(flush); 

    for (i = 0; i < NO_THREADS; ++i) { 

     starts[i] = i; 

     if(pthread_create(threads + i, NULL, (void *) &write_buffer, (void *)(starts + i))) { 
      fprintf(stderr, "Error creating thread no %d\n", i); 
      return EXIT_FAILURE; 
     } 
    } 

    for (i = 0; i < NO_THREADS; ++i) { 
     if(pthread_join(threads[i], NULL)) { 
      fprintf(stderr, "Error joining thread\n"); 
      return EXIT_FAILURE; 
     } 
    } 

    puts("Done"); 

    return EXIT_SUCCESS; 
} 

С помощью ПФ, в 2 нити записи файла в 31.33 секунд. Без, это достигается после минут ...

ответ

0

Когда вы используете /dev/rdisk0s4 вместо /path/to/normal/file%d, за каждую запись, которую вы выполняете, ОС выдаст диск ввода-вывода. Даже если этот диск является SSD, это означает, что время в оба конца, вероятно, составляет не менее нескольких сотен микросекунд в среднем. Когда вы пишете файл вместо этого, файловая система фактически не выпускает ваши записи на диск до более поздней версии. Linux man page описывает эту скважину:

Успешный возврат из write() не гарантирует, что данные были записаны на диск. Фактически, при некоторых ошибках реализации он даже не гарантирует, что пространство было зарезервировано для данных. Единственный способ убедиться в том, что вы вызовете fsync (2) после того, как вы закончите запись всех ваших данных.

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

В целом, писать хорошие системные тесты невероятно сложно, особенно если вы не знаете лот о системе, которую вы пытаетесь протестировать. Я бы рекомендовал использовать готовый инструментарий для тестирования производительности файловой системы Unix, если вы хотите получить качественные результаты - в противном случае вы могли бы потратить буквально всю жизнь на изучение патологий производительности ОС и FS, которые вы тестируете ... не то, что плохая вещь, если вы заинтересованы в ней, как я :-)