2011-06-21 13 views
19

W oryginalnej implementacji vmsplice(), it was suggested, że jeśli miałeś bufor użytkownika-lądowania 2x maksymalną liczbę stron, które zmieściłyby się w potoku, to powodzenie vmsplice() w drugiej połowie bufora zagwarantować, że jądro zostało wykonane przy użyciu pierwszej połowy bufora.vmsplice() i TCP

Ale to nie była prawda po wszystkim, a szczególnie dla TCP, strony jądra będą przechowywane do momentu otrzymania ACK z drugiej strony. Naprawiono to jako przyszłą pracę, a zatem dla TCP jądro wciąż musiałoby kopiować strony z potoku.

vmsplice() ma opcję SPLICE_F_GIFT, która sortuje, zajmuje się tym, ale problem polega na tym, że ujawnia to dwa inne problemy - jak skutecznie pobierać nowe strony z jądra i jak zmniejszyć koszowanie pamięci podręcznej. Pierwszym problemem jest to, że mmap wymaga, aby jądro usunęło strony, a drugim problemem jest to, że chociaż mmap może używać fantazyjnej funkcji kscrubd w jądrze, zwiększa to działający zestaw procesu (usuwanie kosza podręcznego).

Na tej podstawie, mam następujące pytania:

  • Jaki jest obecny stan powiadamiania o bezpiecznej przestrzeni użytkownika ponownego wykorzystywania stron? Szczególnie interesują mnie strony splice() d na gnieździe (TCP). Czy coś się wydarzyło w ciągu ostatnich 5 lat?
  • Czy aktualna najlepsza praktyka w zakresie zerowego kopiowania na serwerze TCP jest lepsza od dzisiejszych?
+1

Go prosić [email protected] – ydroneaud

Odpowiedz

5

Tak, ze względu na trzymanie się stron TCP przez czas nieokreślony, nie można użyć schematu podwójnego buforowania wspomnianego w przykładowym kodzie. Ponadto w moim przypadku użycia strony pochodzą z okrągłego bufora, więc nie mogę podarować stron do jądra i przydzielić nowe strony. Mogę potwierdzić, że widzę uszkodzenie danych w otrzymanych danych.

Uciekłem się do odpytywania poziomu kolejki wysyłkowej gniazda TCP, dopóki nie sprowadzi ona do 0. To naprawia uszkodzenie danych, ale jest nieoptymalne, ponieważ drenaż kolejki wysyłania do 0 wpływa na przepustowość.

n = ::vmsplice(mVmsplicePipe.fd.w, &iov, 1, 0); 
while (n) { 
    // splice pipe to socket 
    m = ::splice(mVmsplicePipe.fd.r, NULL, mFd, NULL, n, 0); 
    n -= m; 
} 

while(1) { 
    int outsize=0; 
    int result; 

    usleep(20000); 

    result = ::ioctl(mFd, SIOCOUTQ, &outsize); 
    if (result == 0) { 
     LOG_NOISE("outsize %d", outsize); 
    } else { 
     LOG_ERR_PERROR("SIOCOUTQ"); 
     break; 
    } 
    //if (outsize <= (bufLen >> 1)) { 
    if (outsize == 0) { 
     LOG("outsize %d <= %u", outsize, bufLen>>1); 
     break; 
    } 
}; 
+0

Masz na myśli zdecydowanie wpływa na przepustowość – Spudd86

+1

według https://netdevconf.org/2.1/papers/netdev.pdf „takie metody są nieprecyzyjne i ERROR- Pusta kolejka transmisji nie oznacza, że ​​dane zostały pozostawione przez urządzenie . Pakiety mogą na przykład czekać w kolejce nadawczej urządzenia w kodzie nadawczym , jeśli instancja działa ". Znalezione przez LWN https://lwn.net/Articles/726917/, dostępne dla nie-subskrybentów po 7-14 dniach. – sourcejedi