Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 11
  1. #1
    Utente di HTML.it
    Registrato dal
    Oct 2016
    Messaggi
    11

    Problema di prestazioni I/O su File

    Salve a tutti...mi sono appena iscritto a questo forum (ringrazio gli amministratori per aver accettato la mia domanda di iscrizione);ho iniziato da poco a studiare e programmare in Java, ma ho una buona esperienza di programmazione C e C++. Traducendo in Java alcuni programmi C, ho avuto uno sconcertante problema (spero dipenda soltanto dalla mia poca esperienza su Java). Un programma molto semplice, che deve soltanto generare 2 miliardi di numeri interi Random e stamparli su un file in formato binario, termina in circa 10 minuti nella versione C , mentre in Java per terminare la stampa su file devo aspettare quasi 3 ore...posto di seguito il codice java

    codice:
    import java.io.*; 
    import java.util.Random; 
    import javax.swing.JOptionPane; 
     
     
    public class G_FILEF{ 
         
         
        public static void main(String[] args) throws IOException{ 
        try(DataOutputStream oput = new DataOutputStream(new FileOutputStream("DATIA1.dat"));){  
                    int D, i, x, qmin, qmax;Random random = new Random();final int RBMAX=3000000; 
            String letta = JOptionPane.showInputDialog("Inserisci N_dati1:");D=Integer.parseInt(letta);oput.writeInt(D);System.out.print("\n"); 
            letta = JOptionPane.showInputDialog("Inserisci [INF_T1]=");qmin=Integer.parseInt(letta);letta = JOptionPane.showInputDialog("Inserisci [SUP_T1]=");qmax=Integer.parseInt(letta); 
            oput.writeInt(qmin);oput.writeInt(qmax); 
         
            for(i=0;i<D;i++){x=1+random.nextInt(RBMAX-1);oput.writeInt(x);if(i%10000000==0)System.out.print(i+"->"); }
             
            oput.close(); 
            } 
         
           
        return; 
        } 
    } 
    
    è possibile in qualche modo avere un tempo di esecuzione piui' vicino a quello del programma in versione C?
    Ultima modifica di JFrank0; 08-10-2016 a 04:13

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da JFrank0 Visualizza il messaggio
    è possibile in qualche modo avere un tempo di esecuzione piui' vicino a quello del programma in versione C?
    Inizia con il mettere tra il DataOutputStream e il FileOutputStream un BufferedOutputStream. Questo permette di "bufferizzare" l'output, in pratica le scritture fisiche sul file avvengono solo ogni tanto e a blocchi molto più grossi (per default il buffer in BufferedOutputStream è di 8192 byte ma si può configurare da un costruttore). Non ad ogni singolo int come invece fai adesso, che risulterebbe sicuramente "pesante" se quel D è molto alto.
    Assicurati anche di fare un flush() alla fine poco prima del close().



    P.S. il codice è scritto parecchio male come forma stilistica ... spero sia solo per problemi di copia/incolla.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Utente di HTML.it
    Registrato dal
    Oct 2016
    Messaggi
    11

    Risolto con BufferedOutputStream

    Grazie andbin...dopo aver inserito BufferedOutputStream e flush la differenza tra C e Java non è piu' percettibile vedendo scorrere sullo schermo quella freccia con il numero di interi stampati che ho inserito proprio per rendermi conto da subito del tempo che ci vuole per terminare l'esecuzione....(non ho avuto ancora il tempo per fare la verifica completa, che credo faro' in serata) - perdona la mia ignoranza, come ho gia' detto sono un principiante sul Java..come posso introdurre e configurare un costruttore per una classe come BufferedOutputStream importata dalla libreria di Java il cui codice non è incluso all'interno del programma ...puoi farmi un esempio con qualche riga di codice per favore?
    Ultima modifica di JFrank0; 08-10-2016 a 17:51

  4. #4
    Quote Originariamente inviata da JFrank0 Visualizza il messaggio
    è possibile in qualche modo avere un tempo di esecuzione piui' vicino a quello del programma in versione C?
    Ciao.
    Ho fatto qualche prova al volo, come suggerito dal buon andbin, semplicemente con:

    codice:
    try (DataOutputStream oput = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("DATIA1.txt")))) { ...

    ha impiegato 436657,6 ms, ovvero 7,3 minuti, che già dovrebbe andar bene (chiaramente i tempi sono indicativi, comunque sono su un vecchio macBook del 2008 e Osx, SSD, 8GB).

    Ho provato poi qualcosa con NIO:

    codice:
    ByteBuffer buffer = ByteBuffer.allocateDirect(capacity);
    ...
    FileOutputStream fos = new FileOutputStream("DATIA1.txt", append); 
    FileChannel fc = fos.getChannel();
    fc.write(buffer);

    ha impiegato 71073,9 ms (poco più di 1 minuto)

    Chiaramente non puoi allocare direttamente un ByteBuffer di 2_000_000_000*4, c'è da fare qualche giro in più -e magari ci sono metodi migliori-.

    Se riesci, poi posta i tempi che ottieni

  5. #5
    Utente di HTML.it
    Registrato dal
    Oct 2016
    Messaggi
    11
    Grazie andy_concept...impressionante con NIO! ...ma FileOutputStream va bene solo per i file in formato testo..io sto' lavorando col formato binario...comunque non voglio approfittare troppo della vostra disponibilita'....puoi consigliarmi un manuale di Java .. o documentazione reperibile sul web...dove poter studiare tutte queste belle classi di I/O...

  6. #6
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da JFrank0 Visualizza il messaggio
    ma FileOutputStream va bene solo per i file in formato testo..
    No, FileOutputStream va bene per "qualunque" tipo di file. FileOutputStream sa fare solamente una cosa: scrivere byte su un file nel file-system. Non sa fare altro, non sa "bufferizzare", non sa nulla di "caratteri" di testo. Solo byte e basta. Ma cosa siano questi byte, è assolutamente indifferente per FileOutputStream ... dipende da cosa c'è (eventualmente) "al di sopra" del FileOutputStream.
    Se la classe decoratore che hai al livello più alto è es. DataOutputStream è perché vuoi scrivere un file binario e più precisamente vuoi scrivere facilmente e comodamente valori primitivi composti da più byte come short, int, long ecc...
    Se invece la catena delle classi di I/O la fai ad esempio con: BufferedWriter -> OutputStreamWriter -> FileOutputStream allora è perché vuoi scrivere un file di testo (possibilmente anche con un charset specifico) e quasi certamente fatto "a righe".

    FileOutputStream è solo un "componente" al livello più basso, non incapsula un'altra classe di I/O e va direttamente sul file-system. Ma come lo usi dipende dai "decoratori" che metti uno sopra l'altro al di sopra di FileOutputStream.

    Quote Originariamente inviata da JFrank0 Visualizza il messaggio
    puoi consigliarmi un manuale di Java .. o documentazione reperibile sul web...dove poter studiare tutte queste belle classi di I/O...
    Il tutorial ufficiale Oracle

    Java I/O, 2nd Edition - O'Reilly Media
    Ultima modifica di andbin; 08-10-2016 a 22:59
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  7. #7
    Utente di HTML.it
    Registrato dal
    Oct 2016
    Messaggi
    11
    ...io sto' studiando su Goodrich Tamassia.....ma il tutorial officiale Oracle sarà di certo piu' completo.... nonostante abbia letto solo i primi 2 capitoli del mio libro...sono riuscito a tradurre completamente dal C, compilare ed eseguire
    un programma a cui ho lavorato ultimamente che implementa una nuova struttura dati per la gestione di grandi volumi di dati sulla memoria esterna; siccome io non ho studiato Informatica (laurea in Fisica è il mio titolo di studio) e ho imparato da solo a programmare in C e C++, per avere una valutazione professionale di questo lavoro ne ho parlato con alcuni Prof Universitari di Ing.Informatica...tutti mi hanno giudicato il programma molto interessante dal punto di vista teorico...soprattutto in relazione alla quantita' di dati che si possono gestire su un computer dello standard commerciale, senza dotazione di hardware partcolarmente potente; in particolare uno di loro mi ha anche detto che questo programma opportunamente modificato per farlo girare in parallelo (su architetture cluster) potrebbe essere applicato per la gestione dei BIG DATA. Allego di seguito una breve descrizione delle principali caratteristiche e funzionalità del programma e se a qualcuno del Forum interessa mi puo' ovviamente contattare per ulteriori dettagli
    Grazie a Tutti!!


    Ultima modifica di LeleFT; 10-10-2016 a 10:18

  8. #8
    Quote Originariamente inviata da JFrank0 Visualizza il messaggio
    ...ma FileOutputStream va bene solo per i file in formato testo..io sto' lavorando col formato binario..
    Similmente a java.io.DataOutputStream.writeInt(int v) sul BufferedOutputStream (che hai usato), con ByteBuffer puoi usare java.nio.ByteBuffer.putInt(int value) che andrai poi (periodicamente) a scrivere java.nio.channels.FileChannel.write(ByteBuffer src). Sul tutorial potrai vedere di che si tratta.
    Era per dire che se ti serve più velocità (magari 8-10 min ti vanno già bene), potresti dare un'occhiata anche in quella direzione: sostanzialmente, NIO e direct buffer (la dimensione più ottimale del buffer la troverai tu).
    Togliendo i print e un contatore, il mio tempo è sceso a 39 secondi (e il file da 8GB è scritto e sta lì!).
    In bocca al lupo per il tuo progetto

  9. #9
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,326
    @JFrank0: hai aperto una discussione in merito nel forum "Programmazione"... oltre che in svariati altri forum... non serve attaccarsi alle discussioni altrui per riproporre ulteriormente quanto hai già formulato nell'altro post... oltretutto stai distribuendo il tuo numero di cellulare in giro per i forum: in questo modo otterrai solo maggiori probabilità di far finire il tuo numero di cellulare nelle liste degli spammer. Fossi in te non lo farei con così tanta leggerezza.


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  10. #10
    Utente di HTML.it
    Registrato dal
    Oct 2016
    Messaggi
    11
    Grazie dei buoni consigli LeleFT.. ma al momento non esiste una web-netiquette che vieta di aprire la stessa discussione su piu' Forum della rete tra loro indipendenti, e la cui unica relazione in comune è quella di occuparsi di Informatica
    Ultima modifica di JFrank0; 12-10-2016 a 16:06

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.