2012-11-13 8 views
5

Ich schreibe viele Sachen, um Bursts einzuloggen und den Datenpfad zu optimieren. Ich baue den Log-Text mit StringBuilder. Was wäre die effizienteste Anfangskapazität, Speicherverwaltung, also würde es unabhängig von JVM gut funktionieren? Ziel ist es, eine Umverteilung fast immer zu vermeiden, die durch eine Anfangskapazität von etwa 80-100 gedeckt werden sollte. Aber ich möchte auch so wenig Bytes wie möglich verschwenden, da die StringBuilder-Instanz im Puffer hängen bleiben kann und verschwendet Bytes auftauchen.Die effizienteste anfängliche Kapazitätsgröße für StringBuilder?

Ich weiß, dies hängt von JVM ab, aber es sollte einen Wert geben, der kleinste Bytes verschwenden würde, unabhängig von der JVM, eine Art "kleinster gemeinsamer Nenner". Ich verwende derzeit 128-16, wobei die 128 eine nette runde Zahl ist, und die Subtraktion ist für den Overhead der Zuweisung. Dies könnte auch als "vorzeitige Optimierung" betrachtet werden, aber da es sich bei der Antwort um eine "Daumenregel" handelt, weiß man, dass sie auch in Zukunft nützlich sein wird.

Ich erwarte nicht "meine beste Vermutung" Antworten (meine eigene Antwort oben ist schon das), ich hoffe, jemand hat dies bereits recherchiert und kann eine wissensbasierte Antwort teilen.

+0

Der Hinweis auf diese Frage hängt von vielen Dingen ab, zB wie lange der Text in einem 'StringBuilder' gespeichert wird etc. Die einzige Möglichkeit dies herauszufinden ist Messen mit einem Speicher- und/oder CPU-Profiler. Es gibt keinen Grund, sich um ein paar Bytes zu sorgen, es sei denn, Sie erstellen Hunderttausende von StringBuilder-Objekten. – Jesper

+1

Mit Abstand der größte Aufwand sind die Kosten von IO. Sofern Sie nicht vorhaben, diese Daten in IO zu schreiben, würde ich mir darüber keine Sorgen machen. –

Antwort

3

Nun, ich endete das Testen selbst kurz, und dann testen Sie einige mehr nach Kommentaren, um diese bearbeitete Antwort zu erhalten.

Mit JDK 1.7.0_07 und Test-App Reporting VM-Namen "Java HotSpot (TM) 64-Bit Server VM", Granularität der StringBuilder Speichernutzung ist 4 Zeichen, bei noch 4 Zeichen zu erhöhen.

Antwort: ein beliebiges Vielfaches von 4 ist gleich gut Kapazität für StringBuilder von Speicherzuweisung Sicht, zumindest auf dieser 64-Bit-JVM.

Getestet durch Erstellen von 1000000 StringBuilder-Objekten mit unterschiedlichen Anfangskapazitäten, in verschiedenen Testprogrammausführungen (um den gleichen anfänglichen Heap-Status zu haben) und Ausdrucken von ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed() davor und danach.

Drucken von Heap-Größen auch bestätigt, die tatsächlich aus Heap für jeden StringBuilder Puffer ist ein gleichmäßiges Vielfaches von 8 Bytes zugewiesen, wie erwartet, da Java-Zeichen 2 Byte lang ist.Mit anderen Worten, das Zuweisen von 1000000 Instanzen mit der Anfangskapazität 1..4 benötigt ungefähr 8 Megabyte weniger Speicher (8 Bytes pro Instanz) als das Zuweisen der gleichen Anzahl von Instanzen mit der Anfangskapazität 5 ... 8.

+0

Haben Sie etwas dagegen, Ihre Testverfahren zu teilen? - Wie schaffen Sie es, die Heap-Nutzung mit einer solchen Granularität zu bestimmen? – JimmyB

+0

Ich habe den Code nicht griffbereit, aber die Heap-Verwendung ging bei jeder Steigerung von 4 Einheiten in der StringBuilder-Anfangskapazität einen Schritt nach oben, war dann ungefähr gleich für 3 nächste Größen, bevor sie beim nächsten Vielfachen von 4 wieder aufsprang. ** Aber ** das sind 4 Zeichen, also 8 Bytes, oder? Danke für die Nachfrage, ich werde morgen auf jeden Fall nochmal testen, um dies zu überprüfen. – hyde

+0

Sie haben also einen Anstieg der Heap-Nutzung in Schritten von 1000000 x 4 Byte beobachtet? - Ich wage nicht zu überlegen, wie viele Bytes des Java-Heapspeichers eine [Datenstruktur] belegen wird, nicht für ein 'char' und nicht für irgendeinen anderen Wert/Typ in irgendeinem Java-Programm. - Unabhängig von der Granularität * des Granulats * ist die Granularität, bei der der GC entscheidet, den Speicher zurück auf den Haufen zu setzen, unbekannt und beeinflußt jede Messung. - Wenn Sie aus Neugier testen und/oder einige Merkmale einer bestimmten JVM messen, gehen Sie vor. - Sonst, ... sehe meine Antwort oben :) – JimmyB

4

Versuchen Sie nicht, in diesem Fall intelligent zu sein.

Ich verwende derzeit 128-16, wo die 128 eine nette runde Zahl ist, und Subtraktion ist für die Zuweisung Overhead.

In Java basiert dies auf völlig willkürlichen Annahmen über das Innenleben einer JVM. Java ist nicht C. Byte-Ausrichtung und dergleichen sind absolut nicht ein Problem, das der Programmierer ausprobieren kann oder sollte versuchen.

Wenn Sie die (mögliche) maximale Länge Ihrer Zeichenfolgen kennen, können Sie diese für die Anfangsgröße verwenden. Ansonsten sind Optimierungsversuche vergebens.

Wenn Sie wirklich wissen, dass große Mengen an Ihren StringBuilder s für sehr lange Zeiträume um sein (was nicht ganz das Konzept der Protokollierung passen), und Sie wirklich das Bedürfnis verspüren, zu versuchen, die JVM zu überzeugen Um einige Bytes Heapspeicher zu sparen, können Sie versuchen, trimToSize() zu verwenden, nachdem die Zeichenfolge vollständig erstellt wurde. Aber solange Ihre Strings keine Megabytes verschwenden, sollten Sie sich wirklich auf andere Probleme in Ihrer Anwendung konzentrieren.

Verwandte Themen