2015-05-05 3 views
0

У меня есть функция, которая в основном делает это:Очень низкая производительность файловой системы

int mmkdir(const char *path, mode_t mode) 
{ 
    struct stat st; 
    if (stat(path, &st) < 0) 
    { 
     if (errno != ENOENT) 
      return -1; 

     if (mkdir(path, S_IWUSR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0 && errno != EEXIST) 
      return -1; 
    } 
    else if (!S_ISDIR(st.st_mode)) 
    { 
     errno = ENOTDIR; 
     return -1; 
    } 
    return 0; 
} 

int fun(int id, int id2) 
{ 
    time_t ts; 
    struct tm timeinfo; 
    char buff[1024], buff1[20], buff2[20], buff3[20]; 

    ts = time(NULL); 
    localtime_r(&ts, &timeinfo); 
    strftime(buff1, sizeof(buff1), "%Y%m%d", &timeinfo); 
    strftime(buff2, sizeof(buff2), "%H", &timeinfo); 

    snprintf(buff, sizeof(buff), "%s/%s", dir, buff1); 
    if (mmkdir(buff, ORDER_FILE_DEFAULT_PERMS) < 0) 
     return -1; 

    len = strlen(buff); 
    snprintf(buff + len, sizeof(buff) - len, "/%s", buff2); 
    if (mmkdir(buff, ORDER_FILE_DEFAULT_PERMS) < 0) 
     return -1; 
    len += strlen(buff2) + 1; 

    strftime(buff3, sizeof(buff2), "%M%S", &timeinfo); 
    snprintf(buff + len, sizeof(buff) - len - 1, "/%010d-%04d-%s%s.%s", 
     id, id2, buff2, buff3, ext); 

    return open(buff, O_WRONLY | O_APPEND | O_CREAT, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH); 
} 

Plese не проверяют на наличие ошибок, это рабочий код. Он в основном называет stat (2), mkdir (2) (иногда) и open (2).

Проблема в том, что когда загрузка I/O на сервере довольно высока, этот фрагмент кода иногда занимает ровно 7 секунд (!!).

Эти файлы, которые эти функции создают расположены в папке в /, который установлен:

/dev/md0 on/type ext4 (rw,errors=remount-ro) 

и может быть до 1000 файлов в одной папке.

В чем может быть проблема? Почему это может занять так много времени? Есть ли неправильная конфигурация?

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

По запросу в комментариях, выход cat /proc/mdstat является:

Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10] 
md3 : active raid1 sdd1[1] sdc1[0] 
     488282000 blocks super 1.2 [2/2] [UU] 

md1 : active raid1 sda2[0] sdb2[1] 
     15624120 blocks super 1.2 [2/2] [UU] 

md2 : active raid1 sda3[0] sdb3[1] 
     1958900 blocks super 1.2 [2/2] [UU] 

md0 : active raid1 sda1[0] sdb1[1] 
     470798200 blocks super 1.2 [2/2] [UU] 

, что означает, что диски хорошо

+5

Итак, когда ваш сервер перегружен с помощью ввода-вывода, операции ввода-вывода занимают некоторое время? Это меня не очень удивляет. – Mat

+1

«Это не весь код, почему весь код медленный?» -> Мы не можем вам на это ответить. Помимо того, что @Mat сказал – Eregrith

+0

@Mat да, это правда, но я думаю, что 7 секунд это слишком много для открытия файла. –

ответ

2

Если эта функция называется существенно больше, чем один раз в час, и папки не удаляются, тогда ваши вызовы mmkdir являются излишними. Я бы выполнил какую-то схему кэширования, в которой вы помните последний час, когда вы создали папку, и пропустите создание новой папки, если вы ее уже создали. Это приведет к удалению двух вызовов stat, что может иметь большое значение для перегруженной системы.

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

+0

Это хорошее предложение, но я не думаю, что это значительно улучшит производительность. Последние файлы остаются в кеше страниц, поэтому не нужно никакого доступа к диску. –

+0

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

+1

@BasileStarynkevitch: Правда, но кеш страниц может быть очищен созданием многих сотен или тысяч новых файлов - кто знает. В любом случае, к сожалению, диагностика конфигурации сервера не подходит для этого сайта - возможно, ServerFault. – nneonneo

Смежные вопросы