GNU/Linux >> Linux Esercitazione >  >> Linux

Le piccole scritture sulla condivisione di rete SMB sono lente su Windows, veloci su CIFS Linux mount

L'endl C++ è definito per produrre '\n' seguito da un flush. flush() è un'operazione costosa, quindi in genere dovresti evitare di utilizzare endl come fine linea predefinito in quanto può creare esattamente il problema di prestazioni che stai riscontrando (e non solo con SMB, ma con qualsiasi ofstream con un flush costoso che includa lo spinning locale ruggine o anche l'ultimo NVMe a un tasso di output ridicolmente alto).

La sostituzione di endl con "\n" risolverà le prestazioni di cui sopra consentendo al sistema di bufferizzare come previsto. Tranne che alcune librerie potrebbero scaricarsi su "\n", nel qual caso hai più mal di testa (vedi https://stackoverflow.com/questions/21129162/tell-endl-not-to-flush per una soluzione che sovrascrive il metodo sync() ).

Ora, per complicare le cose, flush() è definito solo per ciò che accade all'interno dei buffer della libreria. L'effetto dello svuotamento sul sistema operativo, sul disco e su altri buffer esterni non è definito. Per Microsoft.NET "Quando si chiama il metodo FileStream.Flush, viene scaricato anche il buffer di I/O del sistema operativo." (https://msdn.microsoft.com/en-us/library/2bw4h516(v=vs.110).aspx) Ciò rende flush particolarmente costoso per Visual Studio C++ in quanto esegue il round trip della scrittura fino a il supporto fisico all'estremità del tuo server remoto come stai vedendo. GCC d'altra parte dice "Un ultimo promemoria:di solito ci sono più buffer coinvolti rispetto a quelli a livello di lingua/libreria. Anche i buffer del kernel, i buffer del disco e simili avranno un effetto. L'ispezione e la modifica di questi dipendono dal sistema ." (https://gcc.gnu.org/onlinedocs/libstdc++/manual/streambufs.html) Le tue tracce di Ubuntu sembrerebbero indicare che i buffer del sistema operativo/di rete non vengono scaricati dalla libreria flush(). Il comportamento dipendente dal sistema sarebbe una ragione in più per evitare endl e flushing eccessivo. Se stai usando VC++ potresti provare a passare a un derivato di Windows GCC per vedere come reagiscono i comportamenti dipendenti dal sistema, o in alternativa usare Wine per eseguire l'eseguibile di Windows su Ubuntu.

Più in generale è necessario pensare alle proprie esigenze per determinare se lavare ogni linea sia appropriato o meno. endl è generalmente adatto per flussi interattivi come il display (abbiamo bisogno che l'utente veda effettivamente il nostro output, e non in burst), ma generalmente non adatto per altri tipi di flussi, inclusi i file in cui l'overhead di scaricamento può essere significativo. Ho visto app svuotarsi ogni volta che scrivo da 1 e 2 e 4 e 8 byte... non è bello vedere il sistema operativo macinare milioni di IO per scrivere un file da 1 MB.

Ad esempio, un file di registro potrebbe richiedere lo svuotamento di ogni riga se si esegue il debug di un arresto anomalo perché è necessario eliminare l'ofstream prima che si verifichi l'arresto anomalo; mentre un altro file di registro potrebbe non aver bisogno di svuotare ogni riga se sta solo producendo una registrazione informativa dettagliata che dovrebbe essere scaricata automaticamente prima che l'applicazione termini. Non è necessario che sia l'una o l'altra poiché potresti derivare una classe con un algoritmo di svuotamento più sofisticato per soddisfare requisiti specifici.

Confronta il tuo caso con il caso contrastante di persone che devono garantire che i propri dati siano completamente persistenti su disco e non vulnerabili in un buffer del sistema operativo (https://stackoverflow.com/questions/7522479/how-do-i-ensure-data -è-scritto-su-disco-prima-di-chiudere-fstream).

Si noti che come scritto, outFile.flush() è superfluo in quanto scarica un ofstream già scaricato. Per essere pedanti, avresti dovuto usare endl da solo o preferibilmente "\n" con outFile.flush() ma non entrambi.


Le prestazioni delle operazioni su file remoti, come lettura/scrittura, utilizzando il protocollo SMB possono essere influenzate dalla dimensione dei buffer allocati da server e client. La dimensione del buffer determina il numero di round trip necessari per inviare una quantità fissa di dati. Ogni volta che vengono inviate richieste e risposte tra client e server, la quantità di tempo impiegata è pari almeno alla latenza tra le due parti, che potrebbe essere molto significativa nel caso di Wide Area Network (WAN).

Buffer SMB:MaxBufferSize può essere configurato tramite la seguente impostazione di registro:

HKLM\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters\SizeReqBuf

Tipo di dati:REG_DWORD

Intervallo:da 1024 a 65535 (scegli il valore in base alle tue esigenze sopra 5000)

MA LA FIRMA SMB influisce sulla dimensione massima del buffer consentita. Quindi dobbiamo disabilitare anche la firma SMB per raggiungere il nostro obiettivo. Il seguente registro deve essere creato sia sul lato server che, se possibile, anche sul lato client.

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\LanManWorkstation\Parameters

Nome valore:EnableSecuritySignature

Tipo di dati:REG_DWORD

Dati:0 (disabilita), 1 (abilita)


Non ho abbastanza reputazione per lasciare un commento (che penso sarebbe meglio dato il livello di verifica su questa risposta).

Ho notato che una grande variazione nella tua traccia di livello Linux rispetto a Windows è che stai usando SMB1 su Linux e SMB2 su Windows. Forse il meccanismo di oplock batch funziona meglio in samba SMB1 rispetto all'implementazione del lease esclusivo SMB2. In entrambi i casi ciò dovrebbe consentire una certa quantità di cache lato client.

1) Forse prova a impostare un livello di protocollo massimo inferiore in Samba per provare Windows con SMB12) Verifica che gli oplock o i lease esclusivi siano stati eliminati

Spero che questo aiuti :)


Linux
  1. Debian – Cifs perde casualmente la connessione alla condivisione di Windows?

  2. Linux - Mount Cifs Network Drive:autorizzazioni di scrittura e Chown?

  3. Montaggio di una condivisione Windows nel sottosistema Windows per Linux

  4. Come elencare tutti i file in una condivisione di rete Windows SMB

  5. Wannacrypt (wcrypt) può diffondersi tramite un server Linux che serve su SMB?

Invia le tue scansioni a una macchina Linux sulla tua rete

Come montare una condivisione NFS in Linux

Come montare Windows Share su Linux usando CIFS

Come montare Windows Share su Ubuntu Linux

Come condividere la stampante in rete in Linux

Montare l'autorizzazione CIFS negata su Linux - Risolto!