Newsgroup: it.comp.programmare.win32
Titolo: Scrittura su HDD

Buongiorno,
avrei bisogno di sapere quale funzione utilizzare in un programma C++ per
scrivere velocemente su hdd. Mi spiego meglio. Usando la fwrite su blocchi
di 128*1024 unsigned long, ottengo una velocità di circa 13.7 MB/s. Nero mi
dice invece che il mio HDD raggiunge i 26.7 MB/s. Probabilmente cambia la
dimensione del pacchetto scritto, ma ho la sensazione che cambi anche la
funzione per scrivere.
Conoscete qualcosa di meglio della fwrite?
Grazie
Milla
--------------------------------
Inviato via 
http://usenet.libero.it

 Conoscete qualcosa di meglio della fwrite?
In questi casi conviene usare direttamente le API di sistema.
(in Windows: CreateFile, ReadFile(Ex) e WriteFile(Ex))
Kiuhnm


--------------------------------
Inviato via 
http://usenet.libero.it

 Intanto che ci sono, c'è un modo per leggere in DMA?
Windows lo fa già automaticamente per te.
Kiuhnm

 Conoscete qualcosa di meglio della fwrite?
La fwrite() chiama direttamente la WriteFile() in maniera sincrona,
quindi usare quest'ultima non aiuta per nulla. Di solito per ottenere le
massime prestazioni in I/O si utilizza una di queste tecniche:
-I/O asincrono (guarda WriteFileEx); per i normali file funziona solo
sotto a NT/XP/2000.
-Memory mapped file (guarda CreateFileMapping).
-Completion ports, solo sotto a NT/XP/2000. Di queste non ne so quasi
nulla, so che si usano spesso sui programmi server.
-I/O di tipo scatter/gather (anche questo solo sotto a NT/XP/2000). Ne
so ancora meno. :)
Non ti so dire quali siano i guadagni che ti puoi effettivamente
aspettare da ciascuna tecnica, ma tentarle non nuoce.
--
Lorenzo

 -Memory mapped file (guarda CreateFileMapping).
Sono altamente inefficienti, specialmente con file di grosse dimensioni.
Kiuhnm

 Sono altamente inefficienti, specialmente con file di grosse dimensioni.
Veramente io li uso da diverso tempo con estremo successo, specialmente con
file di grosse dimensioni.
E' anzi proprio sui file di una certa dimensione che il guadagno di
prestazioni diventa significativo.
C'è una sola avvertenza: è necessario conoscere la dimensione finale del
file al momento della creazione, a patto di non crearlo enorme e resizarlo
in seguito (operazione che uccide eventuali guadagni).
Con i File Memory Mapped ho ottenuto le performance migliori fino ad ora.

 prestazioni diventa significativo.
Qui si parlava di scrivere dati sull'hard disk a velocità massima.
Ho fatto un test e mentre la WriteFile impiega 81 sec., i MMF ne impiegano
2. Ti pare possibile?
E' ovviamente una virtualizzazione. Nemmeno la FlushFileBuffers() è
affidabile. Sono tutte funzioni che ritornano molto prima che i dati siano
stati effettivamente scritti sull'hard disk quindi è difficile stabilirne i
tempi.
Se partiamo dal presupposto che qualsiasi cosa faccia il sistema operativo
alla fine debba scrivere i dati sull'hard disk nello stesso identico modo
(se non è idiota), è ovvio che a fare la differenza è il processo di
acquisizione dati.
La WriteFile scrive i dati (che possono essere calcolati sul posto)
prendendoli da un buffer (che rimane, nella maggiorparte dei casi, sempre
presente in memoria). I MMF iniziano a lavorare con le pagine della memoria
virtuale e scrivono i dati sull'hard disk un po' alla volta, ritornando al
chiamante molto prima di aver finito.
Al singolo programma può sembrare che questo metodo sia efficientissimo, ma
proviamo a eseguire 20 programmi che fanno un uso intensivo dei file?
La WriteFile scrive direttamente su file, mentre i MMF congestionano
l'intero OS con vari swap.
Sarebbe bello inviare un segnale di shutdown subito dopo un'operazione
tramite i MMF :-)
Kiuhnm


Certo che mi pare possibile, per diversi motivi. Quello che entra in gioco
ANCHE quando si tratta della WriteFile sono numerosi fattori, dal driver
dell'HDD ad eventuali librerie nel compilatore. Ricordo dei test incrociati
che ho fatto con un mio amico programmatore delphi che montava l'Intel
Application Accellerator: su WriteFile e sui MMF avevamo gli stessi identici
tempi, anzi, erano leggermente superiori quelli della WriteFile.
Ergo: se un programmatore deve realizzare una funzione il + veloce
possibile, considerato che cmq Windows ci mette il naso con la gestione
della cache etc, ha senso scegliere la funzione che in termini
d'applicazione risulta essere la + comoda/performante.
A parte questo, quando si usa 2k/XP TUTTI i componenti base del sistema
usano i MMF, dal log degli eventi ad explorer per caricare le immagini degli
eseguibili, passando per la memoria virtuale, senza considerare poi altri
programmi come IIS che li usano massivamente per praticamente ogni cosa. Non
aver fiducia nei MMF e nel modo in cui l'OS li gestisce equivale a dire che
non si ha fiducia nell'OS stesso.
Ergo: è abbastanza stupido non usarli per mancanza di fiducia quando tutto
l'OS ne fa un utilizzo così intensivo. Ovviamente se mandi un segnale di
Shutdown il kernel ha le sue procedure atte ad evitare la perdita di dati,
altrimenti avresti una perdita di dati al giorno, mi sembra ovvio.
A parte questo, è possibile decidere il funzionamento della Cache anche per
i MMF, con gli attributi SEC_NOCACHE, PAGE_NOCACHE e con l'utilizzo di
FlushViewOfFile, per quanto a mio avviso sia abbastanza stupido non
approfittare delle ottimizzazioni fornite dalla cache.

 stupido non approfittare delle ottimizzazioni fornite dalla cache.
Puoi usare tutti gli attributi che ti pare, ma resta il fatto che i MMF sono
più efficienti soltanto quando si devono apportare varie modifiche ai file,
altrimenti sono più veloci le scritture dirette.
Io mi fermo qui: volevo solo dire la mia, non convincere qualcuno.
Kiuhnm

 altrimenti sono più veloci le scritture dirette.
Che bel discorso campato in aria. La scrittura tramite MMF è SEMPRE + veloce
della scrittura su file di grosse dimensioni ANCHE se si tratta di una
singola scrittura. Il motivo per cui non sono + veloci anche su file di
piccole dimensioni è che la creazione d'un oggetto Kernel richiede un
determinato numero di risorse che la semplice apertura d'un file non
richiede, motivo per cui per brevi operazioni di scrittura/lettura non è
consigliabile usarlo, ma nemmeno vietato.
In ogni caso, un operazione di I/O effetuata tramite operazioni di copia
della memoria è SEMPRE più veloce delle corrispondenti operazioni d'I/O su
file come spiegato all'inizio. E' assurdo affermare che un memcpy sia +
lento d'un WriteFile, mi fa davvero sorridere. E qui stiamo parlando
d'accesso sequenziale, se dovessimo parlare d'accesso casuale la differenza
sarebbe ancora + abissale.
Oltre a questo si aggiunge il discorso che i file MMF sfruttano al meglio la
cache di sistema essendo memorizzati/letti a pagine di 4k (esattamente come
per la VM).
Esempio: ultimamente sto programmando un server di Gaming Online. Per la
memorizzazione dei dati ho scelto d'usare semplici e veloci dump della
memoria con file MMF al posto della conversione dei dati in formato testuale
e della scrittura tramite le normali funzioni d'I/O (che ho cmq implementato
per le funzioni d'esportazione).
Questa scelta mi ha portato ad avere worldsave (ogni 15 minuti) della durata
di pochi decimi di secondo laddove con l'utilizzo delle API erano
nell'ordine delle decine di minuti. Il server di test che ho realizzato è
UP&RUNNING da oltre un anno, anno durante il quale è successo davvero di
tutto. Dati persi = 0%, Efficienza = 100%.

Pensala come vuoi.
Kiuhnm

 dimensioni. 
così inefficienti che IIS, usandoli, è il server web per Windows con il 
maggior throughput. Regalati "Inside Microsoft Windows 2000", è un buon 
libro
-- 
  < 
http://www.reactos.com/
 >  Open source clone of Windows NT. Current
      Don't stand, REACT!      version 0.1.0. C, C++ and ASM developers
                               and beta testers are welcome!

 buon libro
Risparmia sui libri e regalati un cervello.
Kiuhnm

 qualcosa di magico.
tu la conosci? io dico che tu conosci l'implementazione di Windows 98


 l'intero OS con vari swap.
ma tu sei sicuro di quello che dici? guarda che sia i filesystem sia il 
Memory Manager, alla fine, interagiscono tutti con il Cache Manager. Il 
vantaggio del mappare i file in memoria è che non serve copiare dati


> così inefficienti che IIS, usandoli, è il server web per Windows

ma non preoccuparti, tesoro, mica si nasce "imparati". E' normalissimo, 
se non ci si aggiorna, finire per toppare clamorosamente, prima o poi


 grosse dimensioni.
Sbrigati, corri a dirlo a qualcuno! Tutti pensano il contrario, e
ottengono ottime prestazioni non sapendo il terribile destino che li
attende. :)
--
Lorenzo

 Conoscete qualcosa di meglio della fwrite?
Dal post si capisce (dato che si parla di MB/s) che ci si riferisce alla
velocità reale.
Windows internamente gestisce la scrittura mediante UDMA (o analogo)
cercando di sfruttare appieno l'hardware.
I dati da scrivere vengono calcolati sul posto, ma molto più velocemente di
quanto possano essere scritti.
Abbiamo 2 strade:
a) scrivere direttamente tutti i dati calcolati su hard disk (in blocchi
adeguatamente grandi)
b) passare attraverso cache e/o MMF e infine scrivere tutto sull'hard disk
(sempre in blocchi adeguatamente grandi).
Mi sapete spiegare come potrà il metodo (b) essere più veloce del metodo
(a)?
Non c'è bisogno di acquistare libri di nessun genere: basta riflettere un
momento. Al limite ci si può leggere il 3° manuale della Intel (IA-32, P4).
La scrittura sull'hard disk è un passaggio obbligato, quindi, evitando
preamboli, raggiungeremo lo scopo in minor tempo.
buffer è piccolo e quindi virtualmente _Fixed_ (o Locked)
a) while
        - nuovi_dati -> buffer
        - buffer -> hdd
    endw
Il calcolo verrà eseguito in multi-threading oppure si utilizzerà la
scrittura ascincrona.
b) while
        - nuovi_dati -> MMF[i]
                probabile PAGE_FAULT -> aggiornamento TLB
        - MMF[i] -> hdd
    endw
Il fatto che i MMF siano di dimensione prefissata è una limitazione di
Windows. Non dovrebbe essere troppo difficile renderli resizeable
(probabilmente esistono già algoritmi a livello accademico in grado di
farlo).
Terminati i metodi lock-free e implementata l'interfaccia per gli hard-disk
ATA, dovrò proprio occuparmi di memoria virtuale.
Ho affermato che i MMF sono inefficienti in generale? Ci mancherebbe altro
(li uso anch'io dopo tutto)!
Kiuhnm

> ha ragione lui. E la memoria virtuale non c'entra, è questione di cache
Ho già rettificato la mia affermazione spiegando che è in *alcuni* windows
che la memoria virtuale è resa tramite FileMapping (Chicago).

 (li uso anch'io dopo tutto)!
Veramente hai detto proprio questo. Comunque se non era questo che
intendevi, è stato un semplice fraintendimento.

 intendevi, è stato un semplice fraintendimento.
Si vede che hai letto proprio male. Si parlava in relazione al problema
esposto e non in generale. Ogni volta bisogna usare il prefisso "Per quanto
riguarda questo problema, "?
Non ho più tempo da perdere in questioni inutili...il thread è saturo...e ho
già ripetuto le cose un milione di volte. Se non vuoi capire arrangiati.
Kiuhnm

 Kiuhnm
Reciprocamente, non ho + tempo da perdere con persone che parlano a vanvera.
Adieu

Buongiorno,
mi dispiace aver creato tutto questo casino, ma vi ringrazio di aver perso
tempo per me!
Volevo premettere che credo di non aver capito una buona fetta di quello di
cui avete discusso, ma non sono neanche una programmatrice professionista!
Forse se vi spiego cosa ho bisogno di fare è più semplice.
Devo acquisire dei dati provenienti da un ADC su bus VME tramite un bridge
PCI-VME che ha una velocità (misurata da me) di circa 72.2 MB/s. Eseguo le
letture dall'ADC in blocchi da mezzo MB. Il mio programma deve prendere
questi dati elaborarli un po' e poi scriverli su HDD. Naturalmente posso
decidere quanti dati scrivere alla volta, il fatto è che devo essere più
veloce possibile per non perdere impulsi in ingresso all'ADC.
In linea teorica il mio programma dovrebbe essere portabile, ma per ora mi
interessa solo ottimizzare le prestazioni sotto win2000 (anzi se dimostro
che è meglio sotto win2000 che non sotto linux probabilmente mi laureo
prima!!;-)).
Ho provato ad ottimizzare la dimensione del pacchetto da scrivere ed ho
ottenuto una velocità di circa 18.5 MB/s con pacchetti da 8 MB.
In questo caso sono utili gli MMF?


"Kiuhnm" <kiu...@softhome.net.invalid> ha scritto nel messaggio
news:desba.56733$zo2.1...@news2.tin.it...

Ma stai impazzendo?

 Milla
Dalla tua descrizione del problema suppongo tu abbia un flusso costante di
dati che dura nel tempo, di cui difficilmente suppongo sarà possibile
calcolare la dimensione finale.
Se usi i MMF con file di cui non conosci le dimensioni finali, puoi ottenere
addirittura un performance loss a seconda dell'implementazione, inoltre
dovresti necessariamente implementare un algoritmo decente che ti permetta
di ridimensionare il file in runtime. Se pensi di farcela, fossi in te farei
almeno un tentativo :-)
Considerata la natura del tuo problema, credo cmq che otteresti maggiori
risultati con una scrittura asincrona utilizzando il meccanismo di notifica
del completamento delle operazioni, basato su IO Completion Ports (IOCP).
Questo però limiterebbe il tuo soft ai soli Win2k/XP. Puoi trovare
informazioni sulle IOCP nell'msdn, con tanto d'esempi esplicativi. T'avviso
subito cmq che richiedono un certo grado di conoscenze, anche in ambiti
diversi (Multithreading, etc).
Ciao :-)

 diversi (Multithreading, etc).
Non c'è problema per il sistema operativo, i driver del bridge non
supportano altro che 2k e xp!! Oltre linux ovviamente.. :-(
Se credi che sia meglio la scrittura asincrona anche con le ultime cose che
ti ho detto, mi metto a studiare, ho solo paura di imbarcarmi in qualcosa di
troppo grande quindi prima chiedo! Cmq qualcosina so già, il mio programma è
già multithread!!! ;-)
Ti ringrazio tanto per l'aiuto.
Ciao :-)


 MB/s. Eseguo le
Per cui si tratta di scritture totalmente sequenziali. In tal caso credo
che il fattore preponderante diventi appunto il filesystem, in
particolare la frammentazione del file su cui scrivi: prova a
deframmentare l'hard disk, o comunque assicurati che il file sia
contiguo.
Non escluderei nemmeno (ho gia` visto fare cose del genere in casi
simili) di scrivere direttamente su una partizione non formattata in
modo 'raw', saltando a piu` pari il filesystem: si fa sempre con
CreateFile() e WriteFile().
--
Lorenzo

 Al limite ci si può leggere il 3° manuale della Intel (IA-32, P4).
Windows NT non è il tuo VaporwareOS. Windows NT ha un'*architettura*, e 
un *design*, e dev'essere *portabile*. So che ritieni tutto ciò un peso 
terribile da portarsi dietro, ma l'era del DOS, del sistema operativo a 
sottiletta tra applicazioni e hardware, è finita. Il manuale della CPU, 
in questo caso, è così inutile che ti premierei con un Mongolino d'Oro, 
o un Tapiro, se preferisci


 Ma stai impazzendo?
naaah, fa cosě solo perchč č follemente innamorato di me


 già multithread!!! ;-)
Il concetto è che se sai di per certo che il flusso di dati supera o
potrebbe superare la velocità di scrittura delle normali funzioni, devi
trovare un modo per slegare il processo di scrittura dalla velocità di
risposta dell'HDD.
In una situazione del genere farei un thread che acquisisce i dati e li
memorizza in uno o + buffer, quindi con un altro pool di thread effettuerei
una scrittura (anche sincrona) dei dati su File, senza andare
necessariamente a disturbare le IOCP.
Fossi in te proverei un implementazione semplice di questo tipo
innanzitutto. Nel caso da una struttura simile fai in fretta a passare alla
scrittura asincrona+IOCP.
Ciao :-)

 CreateFile() e WriteFile().
Avevo già pensato al problema della frammentazione, ma il mio disco è
praticamente vuoto e non frammentato. Non sapevo si potesse scrivere su una
partizione non formattata, varrebbe la pena di provarlo! :-)


 scrittura asincrona+IOCP.
Correggimi se sbaglio, ma se slego il processo di scrittura da quello di
acquisizione prima o poi saturo la memoria e perdo una valanga di impulsi
tutti in una volta.. Anche se i thread di scrittura sono diversi, al massimo
il thread di lettura verrà eseguito meno frequentemente ma comunque non più
sequenzialmente. Credo che potrebbe essere un miglioramento solo verso la
frequenza limite, ma oltre si incasinerebbe tutto. Non è così?
Grazie per il tempo che mi stai dedicando, mi aiuti molto!


 frequenza limite, ma oltre si incasinerebbe tutto. Non è così?
Considerato che hai tempi d'inattività credo che sia molto improbabile come
ipotesi. Onestamente non so se sarebbe + facile che si saturino i buffer
piuttosto che l'HDD non riesca a stare dietro alle richieste di scrittura.
Diciamo che con il discorso dei buffer almeno puoi inserire un meccanismo
che t'avvisa che hai raggiunto il limite consentito, sarebbe un ottimo banco
di test per verificare l'effettiva mole del trasferimento dati.
Comunque con l'ultima soluzione che t'ho proposto, il discorso dei buffer
viene a cadere poichè scriveresti direttamente su MMF appena avvenuta la
ricezione.

 simili) [...]
seeeh, non esageriamo. Lo farà Oracle DBMS, e non so se e quanti altri. 
Se il problema di Milla (alla fine il suo post non l'ho ancora letto) è 
solo che le scritture sincrone sui file rallentano la lettura dei dati, 
che scriva in asincrono. Non si appesantisce nulla, dato che in Windows 
l'I/O, in realtà, è sempre asincrono, e quello sincrono è solo simulato


 quanti altri.
Mi riferivo a programmi decisamente piu` "custom", usati in campo
industriale.
--
Lorenzo