Visualizzazione dei risultati da 1 a 10 su 20

Hybrid View

  1. #1
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da giannino1995 Visualizza il messaggio
    E' possibile velocizzare ulteriormente questo metodo?
    Sì, e anche abbastanza.
    Innanzitutto utilizzando una classe di I/O in grado di fare del "buffering". Alcune varianti:

    tue scritture -> PrintStream -> BufferedOutputStream -> FileOutputStream
    oppure
    tue scritture -> BufferedWriter -> OutputStreamWriter -> FileOutputStream

    Poi se vuoi comporre una riga intera per volta, certamente non usando la concatenazione delle stringhe ma usando direttamente un StringBuffer/StringBuilder. In alternativa (avendo un "buffering" al di sotto che aiuta), scrivere direttamente i pezzetti senza comporre alcuna stringa più grande.


    Ah, e sarebbe bene fare alla fine un bel flush() e poi il close(). Entrambi sull'oggetto di I/O più "esterno" che hai in quel momento.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  2. #2
    Quote Originariamente inviata da andbin Visualizza il messaggio
    Sì, e anche abbastanza.
    Innanzitutto utilizzando una classe di I/O in grado di fare del "buffering". Alcune varianti:

    tue scritture -> PrintStream -> BufferedOutputStream -> FileOutputStream
    oppure
    tue scritture -> BufferedWriter -> OutputStreamWriter -> FileOutputStream

    Poi se vuoi comporre una riga intera per volta, certamente non usando la concatenazione delle stringhe ma usando direttamente un StringBuffer/StringBuilder. In alternativa (avendo un "buffering" al di sotto che aiuta), scrivere direttamente i pezzetti senza comporre alcuna stringa più grande.


    Ah, e sarebbe bene fare alla fine un bel flush() e poi il close(). Entrambi sull'oggetto di I/O più "esterno" che hai in quel momento.



    Scrittura lenta: 18.74 secondi
    Scrittura veloce: 0.246 secondi



    P.S.: Più la dimensione cresce più il divario cresce, sembra impossibile!

    grazie andbin, sei il numero 1!

    Ho trovato lo script nel capitolo NIO del mio manuale ma la differenza è notevole!!!

    Ti devo chiedere 2 cose:

    1) Sapresti spiegarmi in modo semplice senza troppi giri di parole il motivo per cui il nuovo script è riesce ad essere più veloce?

    2) Con il nuovo codice si hanno dei contro oltre che dei pro?

    3) Si scrive prima nella ram e poi sul disco o direttamente sul disco con questi sistemi?

    4) Esiste qualcosa di ancora più veloce? Era questo che avevi in testa? (buttaci un occhio magari riesci a migliorarlo ancora... anche solo di qualche miliardesimo di nanosecondo... )

    Ecco il nuovo codice:

    codice:
    try (OutputStream fout = new BufferedOutputStream(
                    Files.newOutputStream(Paths.get(nome_file)))) {
                String riga = "";
                for (int i = 0; i < matrice.length; i++) {
                    riga = "";
                    for (int j = 0; j < matrice[0].length; j++) {
                        if (j < matrice[0].length - 1) {
                            riga = riga + matrice[i][j] + ",";
                        }
                        if (j == matrice[0].length - 1) {
                            riga = riga + matrice[i][j] + "\n";
                        }
                    }
                    fout.write(riga.getBytes());
                    riga = "";
                }
            } catch (InvalidPathException e) {
                System.out.println("URL scelto inesistente.");
                System.out.println("Path Error " + e);
            } catch (IOException e) {
                System.out.println("Errore nella scrittura del file .CSV");
                System.out.println("I/O Error: " + e);
            }
    lo lascio servisse a qualche altro forumisto di html.it.
    Ultima modifica di giannino1995; 21-01-2014 a 21:20
    Più pratica in futuro...

  3. #3
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da giannino1995 Visualizza il messaggio
    4) Esiste qualcosa di ancora più veloce? Era questo che avevi in testa?
    Ehm .... no, non era esattamente questo a cui pensavo. Per almeno 2 motivi.

    Prima avevo fatto l'esempio della "catena" di classi che si possono usare. All'esterno sarebbe meglio avere un PrintStream o un BufferedWriter (rivedi risposta #2).
    Quello che hai fatto tu, cioè usare direttamente uno "stream" e scrivere byte usando riga.getBytes() è di per sé tecnicamente corretto.
    Ma sarebbe stato meglio scrivere "a caratteri" (appunto PrintStream o BufferedWriter) perché è più chiaro ma oltretutto sotto sotto hanno sicuramente più possibilità di ottimizzare la scrittura.

    Come seconda cosa: hai continuato ad usare la "concatenazione" delle stringhe all'interno dei cicli for, cosa che in quel modo è inefficiente.
    Sarebbe meglio:
    - Usare direttamente StringBuffer/StringBuilder per comporre la riga.
    oppure
    - Visto che di "sotto" c'è una bufferizzazione, scrivere direttamente i pezzetti della riga, senza comporre una stringa unica.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  4. #4
    Scrivere subito senza usare la variabile riga incrementa ulteriormente le performance. Pazzesco!!!

    codice:
    package prova;
    
    import java.io.BufferedOutputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.nio.file.Files;
    import java.nio.file.InvalidPathException;
    import java.nio.file.Paths;
    import java.security.NoSuchAlgorithmException;
    
    class Esempio {
    
        static void Stampa1(Object[][] matrice, String nome_file) {
            String lineSeparator = System.getProperty("line.separator");
            try (OutputStream fout = new BufferedOutputStream(
                    Files.newOutputStream(Paths.get(nome_file)))) {
                String riga = "";
                for (int i = 0; i < matrice.length; i++) {
                    riga = "";
                    for (int j = 0; j < matrice[0].length; j++) {
                        if (j < matrice[0].length - 1) {
                            riga = riga + matrice[i][j] + ",";
                        }
                        if (j == matrice[0].length - 1) {
                            riga = riga + matrice[i][j] + lineSeparator;
                        }
                    }
                    fout.write(riga.getBytes());
                    riga = "";
                }
            } catch (InvalidPathException e) {
                return;
            } catch (IOException e) {
                return;
            }
        }
    
        static void Stampa2(Object[][] matrice, String nome_file) {
            String lineSeparator = System.getProperty("line.separator");
            try (OutputStream fout = new BufferedOutputStream(
                    Files.newOutputStream(Paths.get(nome_file)))) {
                for (int i = 0; i < matrice.length; i++) {
                    for (int j = 0; j < matrice[0].length; j++) {
                        if (j < matrice[0].length - 1) {
                            fout.write((matrice[i][j] + ",").getBytes());
                        }
                        if (j == matrice[0].length - 1) {
                            fout.write((matrice[i][j] + lineSeparator).getBytes());
                        }
                    }
                }
            } catch (InvalidPathException e) {
                return;
            } catch (IOException e) {
                return;
            }
        }
    
        public static void main(String[] args) throws NoSuchAlgorithmException {
            int righe = 600;
            int colonne = 600;
            Object[][] matrice = new Object[righe][colonne];
            for (int i = 0; i < righe; i++) {
                for (int j = 0; j < colonne; j++) {
                    matrice[i][j] = "Indici della cella della matrice: i = " + i
                            + " j = " + j;
                }
            }
            long start = System.currentTimeMillis();
            Stampa1(matrice, "prova.csv");
            long fine = System.currentTimeMillis();
            long tempo = fine - start;
            System.out.println((double) tempo / 1000);
            long start2 = System.currentTimeMillis();
            Stampa2(matrice, "prova2.csv");
            long fine2 = System.currentTimeMillis();
            long tempo2 = fine2 - start2;
            System.out.println((double) tempo2 / 1000);
        }
    }


    ti dico solo una cosa:

    Output del programma:
    10.809
    0.967
    Più pratica in futuro...

  5. #5
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Lo vuoi capire che:

    a) stai comunque ancora usando la concatenazione delle stringhe, che così in un loop è inefficiente.
    b) non si dovrebbero fare catch con un banale return. Così, in generale, "zittisci" le eccezioni.
    c) per fare calcoli sui tempi che siano un po' attendibili, bisognerebbe ripetere il codice un po' di volte e prendere almeno la media dei tempi.

    ?


    Ti spiace provare esattamente questo:

    codice:
    import java.io.*;
    import java.nio.file.*;
    
    public class ProvaTempiScritturaMatrice {
        public static void main(String[] args) {
            int righe = 600;
            int colonne = 600;
            final Object[][] matrice = new Object[righe][colonne];
            for (int i = 0; i < righe; i++) {
                for (int j = 0; j < colonne; j++) {
                    matrice[i][j] = "Indici della cella della matrice: i = " + i
                            + " j = " + j;
                }
            }
    
            Runnable andbinCode = new Runnable() {
                public void run() {
                    try {
                        writeMatrix("prova.csv", matrice);
                    } catch (IOException e) {
                        System.out.println(e);
                    }
                }
            };
    
            Runnable gianninoCode = new Runnable() {
                public void run() {
                    Stampa2(matrice, "prova.csv");
                }
            };
    
            System.out.println("andbin code   : " + timeTest(andbinCode) + " millisecondi");
            System.out.println("giannino code : " + timeTest(gianninoCode) + " millisecondi");
        }
    
        public static double timeTest(Runnable r) {
            int count = 100;
            double milliSum = 0;
    
            for (int i = 0; i < count; i++) {
                long begin = System.nanoTime();
                r.run();
                long end = System.nanoTime();
                milliSum += (end - begin) / 1000000.0;
            }
    
            return milliSum  / count;
        }
    
    
        /*---- andbin ----*/
        public static void writeMatrix(String filename, Object[][] matrix) throws IOException {
            FileOutputStream fos = new FileOutputStream(filename);
            OutputStreamWriter osw = new OutputStreamWriter(fos);
            BufferedWriter bw = new BufferedWriter(osw);
    
            try {
                for (int r = 0; r < matrix.length; r++) {
                    for (int c = 0; c < matrix[r].length; c++) {
                        if (c > 0) {
                            bw.write(",");
                        }
    
                        bw.write(String.valueOf(matrix[r][c]));
                    }
    
                    bw.newLine();
                }
            } finally {
                try { bw.close(); } catch (IOException e) {}
            }
        }
    
    
        /*---- giannino1995 ----*/
        static void Stampa2(Object[][] matrice, String nome_file) {
            String lineSeparator = System.getProperty("line.separator");
            try (OutputStream fout = new BufferedOutputStream(
                    Files.newOutputStream(Paths.get(nome_file)))) {
                for (int i = 0; i < matrice.length; i++) {
                    for (int j = 0; j < matrice[0].length; j++) {
                        if (j < matrice[0].length - 1) {
                            fout.write((matrice[i][j] + ",").getBytes());
                        }
                        if (j == matrice[0].length - 1) {
                            fout.write((matrice[i][j] + lineSeparator).getBytes());
                        }
                    }
                }
            } catch (InvalidPathException e) {
                return;
            } catch (IOException e) {
                return;
            }
        }
    }

    e dirmi l'output che ottieni?
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

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.