2012-01-16 18 views
7

Mam program testowy. Zajmuje to około 37 sekund na jądrze systemu Linux 3.1. *, Ale zajmuje tylko około 1 sekundy na jądrze 3.0.18 (po prostu zamieniam jądro na tym samym komputerze co poprzednio). Proszę dać mi wskazówkę, jak poprawić ją w jądrze 3.1. Dzięki!Dlaczego fsync() zajmuje dużo więcej czasu na jądrze Linux 3.1. * Niż jądro 3.0

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <unistd.h> 


int my_fsync(int fd) 
{ 
    // return fdatasync(fd); 
    return fsync(fd); 
} 


int main(int argc, char **argv) 
{ 
    int rc = 0; 
    int count; 
    int i; 
    char oldpath[1024]; 
    char newpath[1024]; 
    char *writebuffer = calloc(1024, 1); 

    snprintf(oldpath, sizeof(oldpath), "./%s", "foo"); 
    snprintf(newpath, sizeof(newpath), "./%s", "foo.new"); 

    for (count = 0; count < 1000; ++count) { 
    int fd = open(newpath, O_CREAT | O_TRUNC | O_WRONLY, S_IRWXU); 
    if (fd == -1) { 
     fprintf(stderr, "open error! path: %s\n", newpath); 
     exit(1); 
    } 

    for (i = 0; i < 10; i++) { 
     rc = write(fd, writebuffer, 1024); 
     if (rc != 1024) { 
     fprintf(stderr, "underwrite!\n"); 
     exit(1); 
     } 
    } 

    if (my_fsync(fd)) { 
     perror("fsync failed!\n"); 
     exit(1); 
    } 

    if (close(fd)) { 
     perror("close failed!\n"); 
     exit(1); 
    } 

    if (rename(newpath, oldpath)) { 
     perror("rename failed!\n"); 
     exit(1); 
    } 

    } 

    return 0; 
} 


# strace -c ./testfsync 
% time  seconds usecs/call  calls errors syscall 
------ ----------- ----------- --------- --------- ---------------- 
98.58 0.068004   68  1000   fsync 
    0.84 0.000577   0  10001   write 
    0.40 0.000275   0  1000   rename 
    0.19 0.000129   0  1003   open 
    0.00 0.000000   0   1   read 
    0.00 0.000000   0  1003   close 
    0.00 0.000000   0   1   execve 
    0.00 0.000000   0   1   1 access 
    0.00 0.000000   0   3   brk 
    0.00 0.000000   0   1   munmap 
    0.00 0.000000   0   2   setitimer 
    0.00 0.000000   0  68   sigreturn 
    0.00 0.000000   0   1   uname 
    0.00 0.000000   0   1   mprotect 
    0.00 0.000000   0   2   writev 
    0.00 0.000000   0   2   rt_sigaction 
    0.00 0.000000   0   6   mmap2 
    0.00 0.000000   0   2   fstat64 
    0.00 0.000000   0   1   set_thread_area 
------ ----------- ----------- --------- --------- ---------------- 
100.00 0.068985     14099   1 total 
+0

Skąd wiadomo, że fsync() powoduje spowolnienie? Może być również wywołaniem open(). –

+0

Jakie opcje 'mount' są używane w systemach plików, o których mowa? (Nawiasem mówiąc, zajmuje to około 1,5 sekundy w moim jądrze 2.6.38-12 z Ubuntu; 'system plików ext3',' rw, errors = remount-ro, commit = 0'.) – sarnold

+0

'strace -c ./a. out' podsumuje czas wykonania różnych wywołań systemowych. – sarnold

Odpowiedz

8

Jądro 3.1. * Faktycznie wykonuje synchronizację, 3.0.18 to fałszowanie. Twój kod wykonuje 1000 zsynchronizowanych zapisów. Ponieważ skracasz plik, każde zapisanie powoduje także powiększenie pliku. Tak więc masz 2000 operacji zapisu. Typowe opóźnienie zapisu na dysku twardym wynosi około 20 milisekund na we/wy. Tak więc 2000 * 20 = 40 000 milisekund lub 40 sekund. Wydaje się więc słuszne, zakładając, że piszesz na typowym dysku twardym.

Zasadniczo, po zsynchronizowaniu po każdym zapisie, nie dajesz jądrowi możliwości wydajnego buforowania lub nakładania się zapisów i wymuszania najgorszego przypadku podczas każdej operacji. Co więcej, dysk twardy nakierowany jest na szukanie tam, gdzie dane są zapisane i gdzie metadane są zapisywane raz dla każdego zapisu.

2

Znaleziono przyczynę. Bariery systemowe plików domyślnie włączone w ext3 dla jądra Linux 3.1 (http://kernelnewbies.org/Linux_3.1). Po wyłączeniu barier staje się znacznie szybszy.

+0

Być może przyczyną problemu z wydajnością jest niezwykły wzorzec we/wy testu. Wypróbuj 1000 różnych plików, na przykład, ewentualnie przeplatanych odczytami. Nie jestem pewien, czy wyłączenie barier Fs jest dobrym rozwiązaniem, jeśli w rzeczywistości szukasz bardziej bezpiecznego przechowywania danych (z braku lepszego terminu). – ergosys

Powiązane problemy