Dovresti minimizzare la creazione di molti piccoli oggetti?

9

Quando scrivi qualcosa che crea spesso molti (1000) oggetti piccoli, dovresti cercare di minimizzarlo per le prestazioni? Soprattutto se non si conosce il sistema su cui verrà eseguito, dai desktop di fascia bassa a quelli di fascia alta o addirittura mobile. Per i dispositivi mobili, ho sentito che la creazione di molti oggetti ostacola le prestazioni un bel po ', anche se non so quanto sia vero.

Ho un esempio che mostra bene questa idea. In un programma di grafica, diciamo che esiste un metodo che viene utilizzato per tutti i disegni chiamato idealmente drawPixel(Point) . Potrebbero esserci 1000 di Punti creati e possono essere ripetuti spesso, come in un gioco in cui potrebbe essere chiamato 60+ volte al secondo. In alternativa, drawPixel(int x, int y) potrebbe essere usato per minimizzare la creazione di molti oggetti Point.

In un design orientato agli oggetti, penso che l'uso di Point sia preferibile. Tuttavia, l'uso di tipi primitivi può aumentare le prestazioni. Il guadagno in termini di prestazioni può essere trascurabile nella maggior parte dei casi, ma non sono sicuro di cose come macchine mobili o vecchie. Qual è il guadagno di prestazioni dal fare qualcosa di simile ed è qualcosa che dovrebbe essere preso in considerazione?

    
posta Stripies 14.09.2016 - 03:22
fonte

5 risposte

17

In generale, no , non dovresti evitare di creare oggetti per paura di perdere prestazioni. Ci sono diversi motivi per questo.

  1. Usare gli oggetti è un po 'il punto di usare Java. Evitarli preventivamente è un segnale che la decisione di usare Java potrebbe non essere stata quella giusta per cominciare.
  2. I problemi di rendimento sono notoriamente difficili da prevedere. Mai supponiamo che qualcosa sia un collo di bottiglia. Misura sempre. L'ingegneria delle prestazioni è quasi sempre una questione di apportare piccole modifiche esattamente nel posto giusto. Non puoi predire il posto giusto senza misurare più di quanto puoi prevedere l'effetto di un farmaco senza un esperimento.
  3. Il costo della creazione dell'oggetto è molto sovrastimato. In una JVM moderna equivale sostanzialmente ad incrementare un puntatore (e con i garbage collector generazionali, anche il costo della sua gestione è banale). Ci sono molti testi su internet che ti consigliano di evitare oggetti, di usare il pool di oggetti, ecc. Questo consiglio a volte era giusto negli anni '90; oggi è per lo più obsoleto. È molto improbabile ottenere prestazioni sufficienti a giustificare i costi di sviluppo e la complessità introdotti evitando Oggetti o gestendoli da soli.

Detto questo, ci sono luoghi in cui creare qualcosa in un oggetto non ha senso per cominciare. Passare due coordinate a una routine di disegno potrebbe essere un caso del genere: la coppia di coordinate non ha un'esistenza indipendente, non ha identità, è usata solo una volta e poi immediatamente scartata, ecc.

Se questo è il caso, allora sicuro, vai avanti e passa due int s invece di racchiuderli in un oggetto. Il punto di OOP non è che tutto deve essere un oggetto. Il punto è che gli oggetti rendono più facile lo sviluppo nei luoghi in cui sono la soluzione naturale per un problema di rappresentazione dei dati. Non evitare oggetti dove hanno senso - non li introducono dove non lo fanno.

    
risposta data 14.09.2016 - 07:48
fonte
2

Nell'ottimizzazione delle prestazioni che ho eseguito ( example ) è molto facile per gestione della memoria per essere un colpevole principale. Non mi interessa quanto abbiano sintonizzato con pazzia l'operatore nuovo e il garbage collector, il calcolo più veloce non è un calcolo. Quindi se trovo che il gestore della memoria prende una buona percentuale di tempo, e non posso evitare di creare oggetti , trovo quindi un modo per riutilizzarli, piuttosto che crearne di nuovi.

Lo faccio solo se devo creare oggetti. Per la grafica, di solito non lo faccio. IMHO, la grafica dovrebbe essere disegnata , non costruita . Certo, si potrebbe dire che un'immagine consiste di punti, linee che li collegano, poligoni, testo e così via. Ciò non significa che non hai alternative a creare oggetti prima di disegnarli . Li ho solo disegnati.

C'è un metodo Paint. L'ho ignorato, ho disegnato tutto in una bitmap e poi lo ho trasferito sullo schermo. Sembra istantaneo. Per l'input del mouse, ci sono metodi per sovrascrivere, per rilevare il clic, il trascinamento, qualsiasi cosa.

OOP è una buona idea per determinati motivi. Questi motivi non si applicano nelle situazioni tutte .

    
risposta data 14.09.2016 - 15:13
fonte
2

Vai avanti e usa piccole allocazioni. I moderni gestori di memoria, in particolare l'object manager Java altamente ottimizzato, sono estremamente efficienti. Salva l'ottimizzazione delle prestazioni principali per un programma funzionante.

È estremamente probabile che le prestazioni complessive siano adeguate. Se trovi che non è il caso, quindi, e solo allora , profila le prestazioni del codice. In una lunga carriera di sviluppo del software, ho imparato che i colli di bottiglia non sono quasi mai dove ti aspetti.

Una volta un membro del team ha trascorso diversi giorni a eseguire la ricerca di membri dell'oggetto 20 volte più velocemente. Successo! Tuttavia, la migliore accelerazione generale nell'uso effettivo è stata misurata in centesimi di punto percentuale. La modifica è stata immediatamente annullata, poiché l'accelerazione richiedeva maggiori allocazioni di memoria per membro.

    
risposta data 27.10.2016 - 09:50
fonte
2

Quando pensi all'impatto sulle prestazioni prima di aver scritto il codice, devi pensare che non sai cosa stai facendo.

C'è un sovraccarico di spazio molto piccolo per gli oggetti in java contro i primitivi. Più piccoli sono i tuoi oggetti, maggiore sarà la percentuale di sovraccarico. Tuttavia, ho imparato molto tempo fa che le cose che double n sono nulla rispetto alle cose che moltiplicano n per n.

Quindi, anche se sì, potresti perfezionare un sistema con un impatto della metà delle dimensioni o addirittura un quarto per favore chiediti perché ti interessa davvero. Le soluzioni complicate a questo problema non saranno ben accolte. Soprattutto perché immergersi in tale codice sarà fonte di confusione. I programmatori confusi scrivono codice errato. Scrivono n volte n codice che dovrebbe essere n log n code. E impiegano più tempo per farlo.

Ora, se riesci a salvarmi lo spazio con un trucco che si inserisce in una bella scatola che non devo guardare dentro per la maggior parte del tempo possiamo parlare. Se si tratta di una scatola, posso sostituirmi con un'altra casella quando quella casella funzionerebbe meglio potrei persino pagarla.

    
risposta data 14.09.2016 - 03:43
fonte
1

È semplice: se hai bisogno di 1000 piccoli oggetti, crei 1000 piccoli oggetti e non ti preoccupare. Se hai bisogno di 100 piccoli oggetti, la creazione di 1000 piccoli oggetti è stupida - crea quelli che ti servono e non di più.

Se sei preoccupato per le prestazioni (e se non sei preoccupato per le prestazioni) dovresti avere una funzionalità scritta una volta in un unico posto, che rende l'intero codice più semplice e più comprensibile. Quindi se hai un problema di prestazioni, allora la misurazione potrebbe mostrarti che c'è un posto uno in cui si verifica il problema delle prestazioni, il che rende le cose più facili e solo un posto dove è necessario per cambiarlo. Oppure misurare mostra che questo posto non causa problemi, quindi hai finito.

    
risposta data 27.10.2016 - 10:10
fonte

Leggi altre domande sui tag