String Internierung - String interning
In der Informatik ist String-Interning eine Methode, bei der nur eine Kopie jedes einzelnen String- Werts gespeichert wird, der unveränderlich sein muss . Durch das Internen von Strings werden einige String-Verarbeitungsaufgaben zeit- oder platzsparender auf Kosten des höheren Zeitaufwands beim Erstellen oder Internen des Strings. Die einzelnen Werte werden in einem String-internen Pool gespeichert .
Die einzelne Kopie jedes Strings wird intern genannt und normalerweise von einer Methode der String-Klasse nachgeschlagen, zum Beispiel String.intern() in Java . Alle Konstantenzeichenfolgen zur Kompilierzeit in Java werden mit dieser Methode automatisch interniert.
Stringinterning wird von einigen modernen objektorientierten Programmiersprachen unterstützt , darunter Java, Python , PHP (seit 5.4), Lua , Ruby (mit seinen Symbolen), Julia und .NET-Sprachen . Lisp , Scheme und Smalltalk gehören zu den Sprachen mit einem Symboltyp , bei dem es sich im Grunde um interne Zeichenfolgen handelt. Die Bibliothek des Standard ML of New Jersey enthält einen Atomtyp , der dasselbe tut. Die Selektoren von Objective-C , die hauptsächlich als Methodennamen verwendet werden, sind interne Strings.
Es können auch andere Objekte als Strings interniert werden. Wenn beispielsweise in Java primitive Werte in ein Wrapper-Objekt geboxt werden , werden bestimmte Werte (any , any , any von 0 bis 127 und any oder zwischen -128 und 127) interniert, und zwei beliebige Boxing-Konvertierungen von einem dieser Werte Werte führen garantiert zu demselben Objekt.
booleanbytecharshortint
Geschichte
Lisp führte für seine Symbole den Begriff der internen Zeichenketten ein . In der Vergangenheit wurde die als String-interner Pool verwendete Datenstruktur Oblist (bei Implementierung als verknüpfte Liste) oder Oarray (bei Implementierung als Array) genannt.
Moderne Lisp-Dialekte unterscheiden normalerweise Symbole von Zeichenfolgen; Das Internieren einer gegebenen Zeichenfolge gibt ein vorhandenes Symbol zurück oder erstellt ein neues, dessen Name diese Zeichenfolge ist. Symbole haben oft zusätzliche Eigenschaften, die Strings nicht haben (wie z Nutzungsmuster bzw.
Motivation
Das Internieren von Zeichenfolgen beschleunigt Zeichenfolgenvergleiche, die manchmal ein Leistungsengpass in Anwendungen (wie Compilern und dynamischen Programmiersprachenlaufzeiten ) darstellen, die stark auf assoziative Arrays mit Zeichenfolgenschlüsseln angewiesen sind , um die Attribute und Methoden eines Objekts zu suchen. Ohne Internierung kann das Vergleichen zweier unterschiedlicher Zeichenfolgen das Untersuchen jedes Zeichens von beiden beinhalten. Dies ist aus mehreren Gründen langsam: Es ist von Natur aus O(n) in der Länge der Strings; es erfordert normalerweise Lesevorgänge aus mehreren Speicherbereichen , die einige Zeit in Anspruch nehmen; und die Lesevorgänge füllen den Prozessor-Cache, was bedeutet, dass weniger Cache für andere Anforderungen zur Verfügung steht. Bei internen Strings genügt ein einfacher Objektidentitätstest nach der ursprünglichen internen Operation; dies wird typischerweise als Zeigergleichheitstest implementiert, normalerweise nur ein einzelner Maschinenbefehl ohne jegliche Speicherreferenz.
Das Internen von Zeichenfolgen reduziert auch die Speichernutzung, wenn viele Instanzen desselben Zeichenfolgenwerts vorhanden sind. B. aus einem Netzwerk oder aus einem Speicher gelesen . Solche Zeichenfolgen können magische Zahlen oder Netzwerkprotokollinformationen enthalten. XML-Parser können beispielsweise Namen von Tags und Attributen intern speichern, um Speicherplatz zu sparen. Die Netzwerkübertragung von Objekten über Java RMI-Serialisierungsobjektströme kann Strings effizienter übertragen, da das Handle des String-Objekts bei der Serialisierung anstelle von doppelten Objekten verwendet wird.
Themen
Multithreading
Ein Nachteil ist, dass das Interning von Strings problematisch sein kann, wenn es mit Multithreading gemischt wird . In vielen Systemen müssen String-Interns global über alle Threads innerhalb eines Adressraums (oder über alle Kontexte, die Zeiger gemeinsam nutzen können) sein, daher sind der/die Intern-Pool(s) globale Ressourcen, die für einen sicheren gleichzeitigen Zugriff synchronisiert werden sollten. Während dies nur die String-Erstellung betrifft (wo der Intern-Pool überprüft und gegebenenfalls geändert werden muss) und auf Plattformen, auf denen dies eine sichere Optimierung darstellt, doppelt geprüfte Sperren verwendet werden können, kann die Notwendigkeit eines gegenseitigen Ausschlusses beim Ändern des Intern-Pools teuer sein .
Konflikte können auch reduziert werden, indem der Zeichenfolgenraum in mehrere Pools aufgeteilt wird, die unabhängig voneinander synchronisiert werden können.
Zurückfordern nicht verwendeter interner Strings
Viele Implementierungen interner Strings versuchen nicht, nicht mehr verwendete Strings (manuell oder anderweitig) zurückzufordern. Bei Anwendungen, bei denen die Anzahl interner Strings klein oder fest ist oder die von kurzer Dauer sind, kann der Verlust von Systemressourcen tolerierbar sein. Bei Systemen mit langer Laufzeit, bei denen zur Laufzeit eine große Anzahl von String-Praktikanten erstellt wird, kann es jedoch erforderlich sein, nicht verwendete Praktikanten zurückzufordern. Diese Aufgabe kann von einem Garbage Collector erledigt werden , aber damit dies korrekt funktioniert, müssen schwache Referenzen auf String-Interns im Intern-Pool gespeichert werden.