Hallo,
On 01.05.2013 13:44, Jörg wrote:
> ich habe mit einem Kollegen über die Verwendung einer Schätzung bei der
> Konstruktion der StringBuilder diskutiert.
>
> StringBuilder sb = new StringBuilder(1024);
>
> Ich verwende stets Schätzwerte für die initial Größe, damit der Puffer
> nicht ständig umkopiert wird und den Garbagecollector unter Last nimmt.
so tickt das nicht. Der GC muss den Stringbuilder sowieso wegräumen; das
ist eine typisches temporäres Objekt. Únd wenn Du ihn unnötig groß
machst muss er /mehr/ wegräumen. Das dauert zwar nicht länger, aber wenn
Du viel Speicher allozierst, muss der GC öfter laufen. Und dadurch
erwächst ein Geschwindigkeitsnachteil.
> Gibt es Informationen über die ungefähre Laufzeit bzw. Ordnung der
> Laufzeit des Garbagecollectors ?
Typische werte liegen bei maximal 10-15% - bezogen auf die CPU-Last des
Programms selbst. Es gibt aber auch Anwendungen, wo der Wert erheblich
niedriger liegt.
> Meine Vorstellung war bisher, dass
> verwaiste Objekte und verwaiste Teilgraphen im Objekt-Raum gesucht und
> gelöscht werden, wobei dann gegebenenfalls entstandene Lücken zu
> größeren Freiräumen zusammen gefasst werden.
Nein, anders herum. Noch referenzierte Objekte werden in die
Verlängerung geschickt, und alles, was am Ende kein Zuhause hat, wird
auf einen Schlag weggeknallt. Naja, das war jetzt die extra kurze
Beschreibung.
> Ist die Laufzeit eher linear oder quadratisch oder noch anders ?
Linear mit was? Mit der Anzahl der zu löschenden Objekte? Nein, das ist
sogar grob constant time. Spannender ist vielmehr, wie viele Objekte
noch gehalten werden müssen. Und ein weiterer, wichtiger Punkt ist, wie
oft der GC ran muss. Je exzessiver ein Programm temporäre Objekte
alloziert, desto öfter muss der GC (im Mittel) klar Schiff machen. Das
ist, wenn Du so willst eine lineare Skalierung.
Das bedeutet, wenn Du wirklich etwas gutes für den GC tun willst, dann
solltest Du möglichst wenige temporäre Objekte erzeugen. Also z.B. nicht
in inneren Schleifen. Ein hundertmal benutzter StringBuilder ist immer
besser als hundert einzelne mit exakt passender Größe.
Das andere Extrem, alles und jedes Objekt irgendwo zu Cachen geht aber
auch nach hinten los, denn dann hat man jede Menge Objekte mit langer
Lebensdauer, die ständig den Speicher zumüllen. Außerdem leidet dann
u.U. die Thread-Lokalität des Speichers und damit auch die CPU
Cache-Effizienz.
Aber es gibt noch viele weitere Einflussfaktoren. So können GCs
typischerweise besonders schlecht mit Objekten mittlerer Lebensdauer
umgehen. Am effektivsten arbeiten sie mit Objekten, die entweder ewig
leben oder weniger lange als die Zeit zwischen zwei kleinen GC-Läufen.
Deswegen sind Caches mit einer eher kurzen Speicherzeit zuweilen
kontraproduktiv.
Marcel