2010-05-06 19 views
10

In einem Programm, das ich schreibe, mache ich eine Menge String-Manipulation. Ich versuche, die Leistung zu erhöhen und frage mich, ob die Verwendung von Char-Arrays eine anständige Leistungssteigerung zeigen würde. Irgendwelche Vorschläge?Java Optimization String vs Char Arrays

+0

@ThePinkPoo: Ihre Frage fehlt in Anforderungen: Was soll Ihre Zeichenfolge enthalten? Der gesamte Bereich von Unicode (in diesem Fall wird die Verwendung von char [] ein großer Schmerz sein, da ein Java * char * TOTALLY INADEQUATE ** ist, um die neuen Unicode-Codepunkte darzustellen, die in Unicode 3.1 und höher eingeführt wurden)? Nur (eine Teilmenge von) ASCII? In diesem letzteren Fall können Sie die gesamte String-Klasse, die nur durch Bytes unterstützt wird, neu implementieren, und es kann eine Menge * sehr * nützlicher Optimierung durchgeführt werden. Schon mal da gewesen, hunderte von Megabyte ASCII-Textdateien in Java verarbeitet ... – SyntaxT3rr0r

Antwort

7

Welche Art von Manipulation machst du? Können Sie ein Codebeispiel posten?

Sie können einen Blick auf StringBuilder werfen, die CharSequence implementiert, um die Leistung zu verbessern. Ich bin mir nicht sicher, ob du deine eigenen rollen willst. StringBuilder ist nicht threadsicher btw ... wenn Sie Thread-Sicherheit wollen, schauen Sie sich StringBuffer an.

+0

Wenn Sie Thread-Sicherheit brauchen, gibt es eine nicht-triviale Chance, dass Sie mehr tun müssen, als nur einen 'StringBuffer' einzuwerfen. Sie könnten Deadlocks und Race Conditions vermeiden, aber die Ergebnisse werden wahrscheinlich nicht mit dem übereinstimmen, was Sie erwartet haben. –

+0

Vielen Dank, ich werde die Ergebnisse erneut implementieren und dann posten. – ThePinkPoo

+0

@Hank: Mit einem nicht-trivialen Update wickelst du deinen eigenen 'synchronisierten (thebuffer) {...}' um ihn herum, aber das brauchst du nicht so oft. Aus diesem Grund wurde 'StringBuilder' eingeführt. um die Kosten des Haltens von Schlössern überhaupt loszuwerden, wenn es nicht benötigt wird (d.h. fast die ganze Zeit). –

2

String ist bereits als Char-Array implementiert. Was hast du vor, anders zu machen? Wie auch immer, zwischen dieser Tatsache und der Tatsache, dass GC für ephemere Objekte extrem schnell ist, wäre ich erstaunt, wenn Sie einen Weg finden würden, die Leistung durch Ersetzen von Char-Arrays zu erhöhen.

Michael Borgwardt Ratschläge über kleine Char-Arrays und StringBuilder und StringBuffer ist sehr gut. Aber für mich ist die Hauptsache, zu versuchen, nicht zu raten, was langsam ist: machen Sie Messungen, verwenden Sie einen Profiler, erhalten Sie bestimmte Fakten. Denn normalerweise entpuppen sich unsere Vermutungen über die Leistung als falsch.

1

Wenn Sie eine sehr große Anzahl von kurzen Strings haben, können Sie mit char[] viel Speicher sparen, was auch mehr Geschwindigkeit aufgrund weniger Cache-Misses bedeutet.

Bei großen Strings ist jedoch die Vermeidung von unnötigem Kopieren aufgrund der Unveränderlichkeit von String die Hauptsache. Wenn Sie viel verketten oder ersetzen, kann die Verwendung von StringBuilder einen großen Unterschied machen. Hier

+0

Michael, könntest du ein bisschen mehr über das Ersetzen von Strings durch char [] lernen? Char [] benötigt etwas weniger Speicherplatz als eine String-Instanz, char [] wird jedoch nicht internalisiert und für viele kurze Strings die Wahrscheinlichkeit, dass einige der Strings gleich sind und internalisiert werden (dh JVM behält eine einzelne Kopie bei)) ist viel höher als für ein paar lange Saiten. –

+0

@Totophil: Es hängt wirklich davon ab, mit welcher Art von Strings Sie arbeiten und was Sie damit machen; Wenn Sie veränderbare Darstellungen verwenden, wird das Internieren irrelevant. –

+0

Michael, stimme zu, es hängt wirklich von den Besonderheiten des Szenarios ab. Und das einzige Szenario, das mir in den Sinn kommt, ist, wenn die Software viele String-Manipulationen "an Ort und Stelle" machen muss. Aber der Ansatz wird keine Hilfe bei der Bewältigung von String-Overheads bieten, die von Verkettungen, Suchen und Vergleichen herrühren. –

2

ist ein Auszug aus dem full source of String class von JDK 6.0:

public final class String implements java.io.Serializable, 
     Comparable<String>, CharSequence { 
     /** The value is used for character storage. */ 
     private final char value[]; 

     /** The offset is the first index of the storage that is used. */ 
     private final int offset; 

     /** The count is the number of characters in the String. */ 
     private final int count; 

Wie Sie intern den Wert sehen kann bereits als ein Array von Zeichen gespeichert ist. Ein Array von Zeichen als Datenstruktur weist für die meisten String-Manipulationen alle Einschränkungen der String-Klasse auf: Java-Arrays wachsen nicht, dh jedes Mal (ok, möglicherweise nicht jedes Mal) müsste Ihr String wachsen, was Sie brauchen würden um ein neues Array zuzuweisen und den Inhalt zu kopieren.

Wie bereits erwähnt, ist es sinnvoll, StringBuilder oder StringBuffer für die meisten String-Manipulationen zu verwenden.

In der Tat den folgenden Code ein:

String a = "a"; 
    a=a+"b"; 
    a=a+"c"; 

Wann wird automatisch zu verwenden String umgewandelt kompiliert werden, kann dies leicht mit Hilfe von javap geprüft werden.

Als Faustregel ist es selten ratsam, Zeit zu investieren, um die Leistung der Kern-Java-Klassen zu verbessern, es sei denn, Sie sind ein Weltklasseexperte, einfach weil dieser Code von den Weltklasseexperten geschrieben wurde erster Platz.

2

Haben Sie Ihre Bewerbung profiliert? Weißt du, wo die Engpässe sind? Das ist der erste Schritt, wenn die Leistung unterdurchschnittlich ist. Nun, das und definieren, was akzeptable Leistungsmetriken sind.

Sobald Sie ein Profil erstellt haben, das einige Aufgaben erledigt, haben Sie einen prozentualen Anteil an Zeit, die Sie für die Ausführung von Aufgaben benötigen. Wenn Sie viel Zeit mit der Manipulation von Strings verbringen, können Sie vielleicht damit beginnen, einige dieser Manipulationen zu cachen?Machst du einige von ihnen immer wieder, wenn du sie nur einmal ausführst (und dieses Ergebnis später wieder verwenden wirst, wenn es nötig ist)? Kopieren Sie Strings, wenn Sie nicht brauchen? Denken Sie daran, java.lang.String ist unveränderlich - so kann es nicht direkt geändert werden.

Ich habe mehrmals während der Optimierung/Leistung Tweaking-Systeme Ich arbeite daran, dass ich nicht weiß, wo die Langsamkeit kommt instinktiv gefunden. Ich habe andere (und schändlicherweise auch mich selbst) Tage damit verbracht, etwas zu optimieren, das keinen Gewinn bringt - weil es nicht der ursprüngliche Flaschenhals war und tatsächlich weniger als 1% der Zeit dafür war.

Hoffen, dass dies hilft Ihnen in die richtige Richtung zeigen.

+0

Ich habe Profiliert und es war nicht zu informativ, da meine Komplexität ziemlich minimal ist. Ich weiß aus dem Profil, dass String-Methoden es töten, auch meine Schleifen innerhalb des Codes. Also werde ich einige der Schleifen ausrollen und StringBuilder verwenden – ThePinkPoo

+0

@ThePinkPoo: Wenn String-Operationen es töten, dann ist die beste Sache zu versuchen, die Anzahl der String-Operationen, die Sie tun, zu reduzieren. Dies kann durch Caching oder ähnliches Verhalten erfolgen. Entschuldigung für die Annahme, dass du kein Profil erstellt hast - ich sehe das oft auf verschiedenen Forenseiten (hier eingeschlossen) und wollte sicherstellen, dass du es tust. :) Viel Glück. – aperkins