2012-08-17 18 views
15

Nel mio codice ruolo Azure, scarica un file da 400 megabyte che viene suddiviso in blocchi da 10 megabyte e archiviato in Blob Storage. Io uso CloudBlob.DownloadToStream() per il download.Perché la scrittura su un MemoryStream è più lenta rispetto a un file?

Ho provato due opzioni. Uno sta usando un FileStream - Creo un "write" FileStream e scarica pezzi uno alla volta nello stesso flusso senza riavvolgere e così finisco con un file originale. L'altra opzione è la creazione di un oggetto MemoryStream passando un numero leggermente più grande della dimensione del file originale della dimensione dello stream (per evitare riallocazioni) e scaricando i blocchi in tale MemoryStream - in questo modo finisco con un MemoryStream contenente i dati del file originale.

Ecco alcuni pseudocodice:

var writeStream = new StreamOfChoice(params); 
foreach(uri in urisToDownload) { 
    blobContainer.GetBlobReference(uri).DownloadToStream(writeStream); 
} 

Ora l'unica differenza è che si tratta di un FileStream in un caso e un MemoryStream nell'altra, tutto il resto è la stessa. Si scopre che ci vogliono circa 20 secondi con un FileStream e circa 30 secondi con un MemoryStream - sì, lo FileStream risulta essere più veloce. Secondo il contatore delle prestazioni \Memory\Available Bytes, la macchina virtuale ha una memoria di circa 1 gigabyte disponibile al momento prima della creazione dello MemoryStream, quindi non è dovuto al paging.

Perché scrivere su un file è più veloce di un MemoryStream?

+4

Sei sicuro che il tuo flusso di memoria non stia cambiando? – Oded

+0

Interessante domanda, se non ci sono impaginazioni su MemoryStream dovrebbe essere molto più veloce. Quale dimensione dell'istanza stai usando? E potresti pubblicare del codice (anche se questo probabilmente non ha importanza dal momento che stai semplicemente chiamando la libreria di Storage Client). –

+2

Hai 1 GB di memoria * fisica * o 1 GB di memoria * virtuale *? – Servy

risposta

3

Jon è probabilmente sulla palla lì. La probabile spiegazione più è,

  1. La memoria è in realtà paging dal hypervisor su disco.
  2. Il file di scambio dell'hypervisor si trova su un disco a bassa velocità (ad esempio disco locale).
  3. Il FileSystem della VM si trova su un disco aziendale veloce (ad esempio SAN).

Indipendentemente dal fatto che la memoria sia più veloce o meno, in realtà non è necessario allocare blocchi di memoria così grandi. Leggi qui lo LOH vs SOH.

+0

Beh, se i dischi coinvolti avessero la stessa velocità (o lo stesso disco) ci aspetteremmo ancora che il file-scrittura battesse la scrittura del file di pagina, perché il file-scrittura sarebbe sequenziale, come nel caso di un disco rotante basato su il disco (sia semplice che RAID, ma non include SSD) è migliore nel caso sequenziale. Il paging tende a non danneggiare la maggior parte del tempo a causa dell'intelligenza che si verifica quando viene eseguita, quindi la memoria paginata batte l'accesso ai file per la maggior parte dei casi, ma non questo. –

+0

Non sono d'accordo. Il paging a cui mi riferisco è il paging di Hypervisor piuttosto che il paging del SO. Non sono la stessa cosa. Lo scambio di hypervisor è sostanzialmente più costoso in quanto non può sapere quali pagine sono più adatte per essere sfogliate. Il secondo è Hypervisor, il paging è spesso nelle distribuzioni su larga scala posizionate sul disco locale del server piuttosto che sullo storage condiviso molto più veloce. –

+0

Nessuno di questi è in disaccordo con l'altro. 1: archiviazione SANS> Paging HV. 2: Sequenziale su disco> casuale su disco. Possono essere totalmente entrambi veri. –

1

Quando si utilizza MemoryStream in modalità di debug (VS), la velocità è molto lenta, anche con piccole quantità di dati. L'esecuzione senza debugger collegato è paragonabile o addirittura più veloce di FileStream.

Per prima cosa mi sono confuso e sono finito qui. Ora sto bene con MemoryStream.

Problemi correlati