2009-09-07 7 views
9

Come può la velocità di uscita essere superiore alla velocità di scrittura del disco rigido?Perl: scrivi mistero della velocità?

Update 1: ho cambiato il seguente:

  1. antivirus spento. Nessun cambiamento.

  2. Inserito nuovo disco fisico e utilizzato la prima partizione per il test. (Il disco per il test iniziale si trovava sull'ultima partizione , separata dalla partizione di sistema, ma sullo stesso disco fisico.). Risultato: esiste lo stesso modello ciclico , ma il sistema è non più non risponde durante il test. La velocità di scrittura è un po 'più alta (potrebbe essere dovuta all'utilizzo della prima partizione e/o non interferire più con la partizione del sistema ). Conclusione preliminare: c'era del tipo di interferenza dalla partizione di sistema.

  3. Installato 64 bit Perl. I cicli sono finiti e tutto è stabile su una scala temporale di 2 secondi: CPU al 55% su single core, velocità di scrittura di circa 65 MB/s.

  4. Provato sull'unità originale con 64 bit Perl. Risultato: da qualche parte nel mezzo. Cicli di 8 secondi, CPU 20-50%, 35 - 65 MB/sec (invece di cicli profondi di 0-100%, 0 - 120 MB/sec). Il sistema è solo moderatamente insensibile. La velocità di scrittura è di 50 MB/sec. Questo supporta la teoria dell'interferenza.

  5. Flusso nello script Perl. Non ancora provato


OK, mi ha passato il first hurdle. Ho scritto un Perl script che può generare un file di testo molto grande (ad esempio 20 GB) e è essenzialmente solo un certo numero di:

print NUMBERS_OUTFILE $line; 

dove $ linea è una lunga stringa con un "\ n" a fine.

Quando lo script Perl inizia la velocità di scrittura è di circa 120 MB/s (coerenza tra ciò che viene calcolata dallo script, Process Explorer e "IO Byte scritti/sec" per il processo di Perl in Performance Monitor.) E 100 % CPU sul single core su cui è in esecuzione . Questo tasso è, credo, superiore alla velocità di scrittura del disco rigido .

Quindi dopo un po 'di tempo (ad esempio 20 secondi e 2,7 GB scritti) l'intero sistema diventa molto poco reattivo e la CPU scende a 0%. Questo ultimo per es. 30 secondi. La velocità media di scrittura su queste due fasi è coerente con la velocità di scrittura del disco rigido . I tempi e le dimensioni menzionati in questo paragrafo variano molto da corsa a corsa. La gamma 1 GB a 4,3 GB per la prima fase è stata finora osservata. Questo è un transcript for the run with 4.3 GB.

Ci sono parecchi di questi cicli di GB di file di testo 9.2 generato nel test:

Enter image description here

Che cosa sta succedendo?


completa Perl script e BAT driver script (HTML formattato con il tag pre). Se sono configurate le due variabili di ambiente MBSIZE e OUTFILE, lo script Perl dovrebbe essere in grado di eseguire invariato su altre piattaforme rispetto a Windows.

Piattaforma: Perl 5.10.0 da ActiveState; (inizialmente a 32 bit, successivamente a 64 bit); build 1004. Windows XP x64 SP2, nessun file di paging, 8 GB di RAM, CPU quad core AMD, dischi rigidi da 500 GB Green Caviar (velocità di scrittura 85 MB/s?).

risposta

5

io sono con tutti gli altri che sta dicendo che il problema è buffer di riempimento e quindi lo svuotamento.Provare ad attivare autoflush per evitare di avere un buffer (in Perl):

#!/usr/bin/perl 

use strict; 
use warnings; 

use IO::Handle; 

my $filename = "output.txt"; 

open my $numbers_outfile, ">", $filename 
    or die "could not open $filename: $!"; 

$numbers_outfile->autoflush(1); 

#each time through the loop should be 1 gig 
for (1 .. 20) { 
    #each time though the loop should be 1 meg 
    for (1 .. 1024) { 
     #print 1 meg of Zs 
     print {$numbers_outfile} "Z" x (1024*1024) 
    } 
} 

buffer può essere buono se avete intenzione di stampare un po ', non lavorare così, stampare una litte, fare un certo lavoro, ecc Ma se stai per far saltare dati sul disco, possono causare comportamenti strani. Potrebbe anche essere necessario disabilitare qualsiasi caching di scrittura che il filesystem sta facendo.

+0

Grazie. Ora ho provato 64 bit Perl (vedi domanda aggiornata), ma il prossimo passo sarà provare ad attivare autoflush. –

+0

Ricorda, potresti anche aver bisogno di modificare il tuo filesystem se mantiene i buffer in giro. –

+1

autoflush effettuerà una chiamata di sistema dopo ogni elemento di stampa. Nel tuo esempio le prestazioni saranno buone perché è 1 MB alla volta. Ma se si stampa 'a', 'b', 'c', 'd' sarà molto brutto perché si tratta di quattro chiamate di sistema di un carattere ogni ... attenzione per quello. –

5

Tutti i dati vengono memorizzati nella cache in buffer prima di essere effettivamente inseriti nel disco fisico. Un buffer dal sistema, un altro all'interno del disco stesso (probabilmente un buffer da 32 MB). Mentre si riempiono questi buffer, il programma viene eseguito alla massima velocità e al 100% della CPU. Una volta che i buffer sono pieni, il programma attenderà il disco, che è molto, molto più lento della memoria e dei buffer, e questa attesa ti fa smettere di consumare tutta questa CPU.

Forse è possibile rendere il codice "attendere il disco" dall'inizio, utilizzando un po 'di Perl equivalente a fflush().

+0

Mi aspetto che ci siano buffer di file. Ma non diverse GB di dimensioni (?) –

+4

Sui sistemi Linux i buffer sono solitamente configurati per diffondersi a quasi tutta la RAM libera. –

+0

Non usa Linux ... –

4

Forse il sistema operativo sta scrivendo su disco il più velocemente possibile (85 MB/s), e sta mettendo l'eccesso di 35 MB/s in un buffer, e quando si riempie, sta mettendo in pausa l'app per svuotare il buffer. Dato che il buffer è esaurito a 85 MB/s, ci si aspetterebbe che occorresse 35/85 = ~ 0,4 volte più a lungo per drenare e riempire. Questo è ampiamente compatibile con il tuo grafico, se io strabismo abbastanza.

È possibile stimare la dimensione del buffer come prodotto del tempo di pausa e della velocità del disco.

3

Guarda il grafico! La linea verde indica la lunghezza media della coda del disco. In un momento, ottiene un picco e la CPU va a 0 in seguito. Anche IO Scritte va a 0. Torna alla normalità finché non viene mostrato un secondo picco. Quindi le scritture CPU e IO tornano alla normalità. Quindi, sia l'IO che la CPU scendono di nuovo, per risalire al prossimo picco della coda. E di nuovo giù, poi di nuovo su ...

Potrebbe essere che il disco stia facendo le scritture fisiche in quel momento. Tuttavia, potrebbe anche essere che il sistema stia facendo una convalida del disco in quel momento, leggendo i dati appena scritti per convalidare le scritture, assicurandosi che i dati siano scritti correttamente.

Un'altra cosa che noto è la dimensione di 2,7 GB. Dato che lo stai facendo su un sistema Windows, divento un po 'sospettoso dal momento che si tratta della quantità di memoria che può gestire Windows, come un processo a 32 bit. Il 64 bit di Windows fornirà l'applicazione fino a 3 GB di RAM (un po 'meno), ma poi ha bisogno di rilasciarlo di nuovo. È possibile utilizzare Process Explorer per verificare la quantità di RAM in uso e la quantità di letture di I/O.

E forse utilizzare una versione a 64 bit Perl ...

+0

Per quanto riguarda 2,7 GB: Non so se sono possibili più di 3 GB, ma può capitare già a 1 GB. Ad esempio, appena prima di scrivere questo, l'ho eseguito di nuovo e la prima fase si è conclusa a 1,2 GB (da qualche parte tra 1139 MB e 1273 MB). –

+0

Cosa intendi per quantità di RAM? Importo per il processo Perl? "Byte privati" per il processo Perl rimane costante a 4 MB durante la corsa. Circa 6.3 GB di RAM sono gratuiti all'avvio dello script. –

+0

Ho appena provato un'altra corsa. Questa volta la prima fase si è conclusa a circa 4,3 GB (tra 4,19 GB e 4,41 GB [4288,3 MB; 4513,7 MB]). Ecco una trascrizione della corsa: http://www.pil.sdu.dk/1/until2039-12-31/PerlPerfTranscript_2009-09-07b.txt –