Fare un metodo statico salva la memoria su una classe di cui avrai molte istanze?

8

In risposta alla risposta di Aaronaught alla domanda in:

Non posso semplicemente utilizzare tutti i metodi statici?

La memoria utilizzata non è inferiore a un metodo statico? Ho l'impressione che ogni istanza di un oggetto porta in giro la propria versione eseguibile di una funzione membro non statica.

Indipendentemente da quanto overhead è coinvolto nella chiamata di un metodo statico, a prescindere dalla scarsa progettazione OO e da possibili mal di testa in fondo alla strada, non utilizza meno memoria in fase di runtime?

Ecco un esempio:

Faccio un vettore di oggetti inizializzati a zero. Ogni oggetto contiene un pezzo di dati (un triangolo composto da nove doppie). Ogni oggetto viene popolato in sequenza dai dati letti da un file .stl. È necessario un solo metodo statico. La corretta progettazione OO impone che un metodo che tratta direttamente i dati sia distribuito a ciascun oggetto. Ecco la soluzione OO standard:

foreach(obj in vec) {
  obj.readFromFile(fileName);
}

Ogni oggetto contiene il codice compilato readFromFile accanto ai dati!

La memoria è più un problema che le prestazioni in questo caso, e ci sono molti dati su un sistema vincolato.

Soluzioni:

  1. Metodo Namespace (ottimo per C ++ ma non possibile in Java)
  2. Un metodo statico nella classe obj. Il codice eseguibile viene tenuto in un posto in fase di esecuzione. C'è un piccolo overhead per chiamare il metodo.
  3. Una classe genitore da cui viene derivato obj, che contiene il metodo privato readFromFile . Chiama con super.callPrivateMethod() che chiama readFromFile . Disordinato, e ancora un po 'di memoria in testa in ogni oggetto.
  4. Implementa readFromFile all'esterno dell'ambito di obj, quindi nella classe vec o nella classe chiamante. Questo, secondo me, rompe l'incapsulamento dei dati.

Mi rendo conto che per grandi quantità di dati un oggetto esplicito per ogni triangolo non è l'approccio migliore. Questo è solo un esempio.

    
posta panlex 03.01.2016 - 05:13
fonte

5 risposte

18

I metodi non vengono archiviati su una base per istanza, anche con metodi virtuali. Sono memorizzati in un'unica posizione di memoria e "conoscono" solo l'oggetto a cui appartengono perché il puntatore this viene passato quando li chiami.

L'unica memoria aggiuntiva richiesta in C ++ è se stai usando metodi virtuali, che richiedono un puntatore aggiuntivo per istanza per puntare alla tabella del metodo virtuale (in Java ovviamente hai sempre una classe base con metodi virtuali, Object , quindi è inevitabile).

Se funzionasse come hai descritto, le lingue OO non sarebbero molto popolari! Sentiti libero di aggiungere tutti i metodi necessari agli oggetti. Non influenzerà l'utilizzo della memoria.

    
risposta data 03.01.2016 - 05:50
fonte
7

Regardless of how much overhead is involved in calling a static method, regardless of poor OO design, and possible headaches down the road, doesn't it use less memory at runtime?

Questo è piuttosto complicato, ma direi "per lo più no".

    
risposta data 03.01.2016 - 14:38
fonte
2

Un metodo dovrebbe essere "statico" (molte lingue usano il termine "metodo di classe" che è molto meglio) se non si riferisce a un'istanza della classe. Dovrebbe essere un metodo di istanza se si riferisce a un'istanza della classe.

Prendere una decisione di progettazione basata sulla vaga possibilità di alcuni risparmi di memoria invece dell'uso corretto dei metodi di classe e dei metodi di istanza è un'idea molto, molto, molto cattiva.

    
risposta data 04.01.2016 - 11:08
fonte
1

In linea di principio, c'è solo una copia del codice, indipendentemente dal fatto che si tratti di funzioni membro statiche o meno:

  • In C ++ puoi facilmente verificarlo guardando l'elenco assemblatore del codice generato.
  • Non sono esperto di Java, ma dalle specifiche JNI puoi dedurre che è la stessa logica: puoi recuperare un singolo riferimento a una funzione e chiamarla più volte per oggetti diversi (passandogli un riferimento di classe come argomento, come così come il riferimento all'oggetto se non è un metodo statico).

L'uso di una funzione statica o non statica non modificherà quindi l'impronta di memoria.

In realtà c'è una differenza molto piccola, sia nel codice generato sia nella memoria consumata nello stack durante il tempo di esecuzione della funzione:

  • Una chiamata alla funzione non statica richiede di passare un riferimento / puntatore all'oggetto su cui viene applicata la funzione / metodo. Ciò richiede di solito una spinta aggiuntiva e istruzioni pop nella sequenza chiamante.
  • Una chiamata a una funzione statica non richiede questo sovraccarico.

Ma questo è veramente trascurabile: stiamo parlando di una o due istruzioni della macchina più o meno rispetto al codice completo. Quindi non è sicuramente qualcosa di cui preoccuparsi.

La differenza di consumo dello stack in fase di esecuzione è limitata al tempo di esecuzione della funzione, alla dimensione di un puntatore. Anche questo è trascurabile, a meno che non si stia pensando a una funzione chiamata ricorsivamente un numero enorme di volte (diversi milioni di volte).

Quindi, in conclusione, condivido pienamente l'opinione gnasher729 : l'ottimizzazione prematura è la radice di tutto il male. Se la funzione è indipendente dall'oggetto rendila statica e questo dovrebbe essere l'unico criterio.

    
risposta data 07.01.2016 - 00:33
fonte
0

È facile concentrarsi su cose come l'ottimizzazione dell'uso della memoria o la riduzione delle linee di codice, ma quando si inizia a dover mantenere programmi che le persone usano / rompono e altri programmatori aggiungono funzionalità a ... e possibilmente introducono bug ... non quello il tuo programma originale potrebbe avere bug che hanno superato i test, vedrai che concentrarsi sulla leggibilità / mantenimento del codice potrebbe essere più importante. Potrei creare un array di bit ad alta velocità per tracciare una serie di punti di dati, ma a meno che non abbia avvolto quell'array di bit in un oggetto con accessorie comprensibili il prossimo programmatore per toccare quel codice probabilmente non lo userà, lo sostituirà o eseguirà qualche orribile stregoneria .

    
risposta data 30.06.2018 - 09:02
fonte

Leggi altre domande sui tag