2009-12-01 18 views
30

Sto costruendo un server Linux ad alte prestazioni (basato su epoll, socket non bloccanti e IO disco asincrono [basato su io_submit/io_getevents/eventfd]). Alcuni dei miei benchmark mostrano che il modo in cui gestisco i socket non è abbastanza efficiente per le mie esigenze. In particolare, mi preoccupo di ottenere dati dal buffer dello spazio utente alla scheda di rete e dalla scheda di rete al buffer userspace (ignoriamo per ora la chiamata sendfile).Prese Linux efficienti (DMA/copia zero)

Da quello che ho capito, la chiamata di lettura/scrittura su un socket Linux non bloccante non è completamente asincrona - il blocco di chiamata di sistema mentre copia il buffer dallo spazio utente al kernel (o viceversa), e solo allora ritorna. C'è un modo per evitare questo sentito in Linux? In particolare, esiste una chiamata di scrittura completamente asincrona che posso eseguire su un socket che restituisce immediatamente, DMA il buffer dello spazio utente sulla scheda di rete, se necessario, e segnalare/impostare un evento/ecc. al termine? So che Windows ha un'interfaccia per questo, ma non ho trovato nulla su questo in Linux.

Grazie!

risposta

1

AFAIK si utilizzano le chiamate più efficienti disponibili se non si utilizza sendfile (2). Vari aspetti del codice di rete efficiente ad alte prestazioni sono coperti da

19

Recentemente si è parlato di linux-kernel sulla fornitura di un'API per qualcosa in questo senso, ma il punto critico è che non è possibile utilizzare DMA dai buffer generali dello spazio utente alla scheda di rete, in quanto:

  • Ciò che appare come dati contigui nello spazio di indirizzi userspace lineare è probabilmente non contigue nella memoria fisica, che è un problema se la scheda di rete non fa scatter-gather DMA;
  • Su molte macchine, non tutti gli indirizzi di memoria fisica sono "DMA-capable". Al momento non è possibile per un'applicazione di spazio utente richiedere specificamente un buffer DMA-capable.

Su kernel recenti, si potrebbe provare a utilizzare vmsplice e splice insieme per raggiungere ciò che si vuole - vmsplice le pagine (con SPLICE_F_GIFT) che si desidera inviare in un tubo, poi splice loro (con SPLICE_F_MOVE) dal tubo nel la presa.

+1

Grazie! Hai idea di quanto sarebbe efficiente leggere/scrivere? In generale, c'è una guida alle "migliori pratiche" da qualche parte per questo genere di cose? Ci sono voluti giorni per setacciare tutte le API di polling e segnalazione, e quindi più tempo per confrontarlo prima di trovare una best practice per i socket multiplexing e l'IO asincrono. Sarebbe davvero d'aiuto trovare una guida alle migliori pratiche sui socket. C'è la pagina dei problemi di C10K, ma la maggior parte delle informazioni ci sono molti anni (che è vecchia nel tempo del kernel), e di solito molto inconcludente. –

+2

'splice' e gli amici sono abbastanza nuovi, quindi non sono sicuro che ci sia ancora qualche tipo di guida sulle" migliori pratiche "per loro. Dovrebbero essere a bassa latenza e zero-copy dove possibile - questo è il loro punto di forza. Potresti provare a chiedere sulle mailing list linux-net e/o linux-kernel. – caf

+2

Sono passati 1,5 anni da questi post, eventuali nuovi sviluppi in questo settore? @caf: sei riuscito a farlo con 'splice'? –