Zeichenketten in Java und in vielen JVM-Sprachen enthalten Unicode-Zeichen und sind mit utf-16 codiert. Es war sehr weitsichtig, schon in den 90er-Jahren an Unicode zu denken und das als alleinige Möglichkeit vorzusehen. Man hat sich so erspart, das Durcheinander zu haben, welche Zeichenkette jetzt in welcher Codierung vorliegt, weil alle gleich sind, und auch zumindest für gängige europäische und westasiatische Sprachen die Handhabung vereinfacht, weil da ein Zeichen zwei Bytes sind. Der Nachteil mit dem etwas größeren Speicherverbrauch spielt fast keine Rolle, weil man mit ein paar Zeichenketten sehr selten an die Grenzen stößt. Mit 64-Bit-CPUs (und 64-Bit-JVM) kann man ja fast beliebig viel Hauptspeicher einsetzen.
Aber es gibt auch Applikationen, die trotzdem mit ihrem Speicherverbrauch an Grenzen stoßen. So könnte man auf die Idee kommen, eigene Zeichenketten zu verwenden, die utf-8 statt utf-16 verwenden. Die entsprechende Konvertierung ist nicht schwierig und sicher im Netz zu finden, sogar in der eigenen Java-Libary. Leider sind die Zeichenketten aber an so vielen Stellen vorgesehen und man kann sie nicht einfach durch eine andere Klasse ersetzen. Was bleibt sind also lästige explizite Konvertierungen. Aber allein mit diesem Ansatz kann man natürlich eine Menge Speicher sparen.
Eine andere Idee wäre es, Zeichenketten zu komprimieren. Wenn sie lang genug sind, funktionieren Algorithmen wie gzip auf einer einzelnen Zeichenkette. Das erschwert natürlich den selektiven Zugriff auf einzelne Teile der Zeichenkette, aber das Problem hat man schon mit utf-8, wo man nicht genau weiß, ab welchem Byte nun das n-te Zeichen beginnt, ohne sie von Anfang an durchzugehen. Aber wir müssen auch damit rechnen, dass es nicht einzelne lange Zeichenketten gibt, sondern sehr viele, die jeweils zu kurz sind, um für sich genommen mit einer Kompression kleiner zu werden. Wenn man nun aber die Gesamtheit der Zeichenketten ungefähr kennt, kann man eine Komprimierung generieren, die für diesen Satz von Zeichenketten gute Ergebnisse bringt. Das bedeutet, dass man ähnlich wie bei der Umstellung von utf-16 auf utf-8 einzelne Byte-Sequenzen der unkomprimierten Zeichenkette durch anderen Byte-Sequenzen für die komprimierte Zeichenkette ersetzt. Die häufig vorkommenden Sequenzen werden durch kürzere ersetzt, die selteneren durch längere. So kann man mit weniger Bytes auskommen. Die Regel, wie das Komprimieren und Dekomprimieren funktioniert, muss man nur einmal für das ganze Programm speichern und nicht wie bei der ersten Idee für den Einsatz von gzip in jeder Zeichenkette einzeln.
Es empfiehlt sich unbedingt, die folgenden Punkte zu beachten:
- Sind wirklich die Zeichenketten ein Problem mit ihrem Speicherverbrauch?
- Lässt sich dieses durch andere, einfachere Optimierungen der Software lösen?
- Lasst es sich durch Hardware lösen?
- Gibt es schon geeignete oder adaptierbare Lösungen im Netz? Oder in der eigenen Organisation?
- Eine neue String-Klasse ist so grundlegend, dass man sie unbedingt gut testen muss. Unit-Tests sollten wirklich ausführlich sein.
Schreibe einen Kommentar