Gefahr von C# Substring-Methode?
Kürzlich habe ich gelesen, bis auf einige Fehler mit der Java substring-Methode - insbesondere in Bezug auf Speicher, und wie java hält eine Referenz auf die ursprüngliche Zeichenfolge. Ironischerweise bin ich auch der Entwicklung einer server-Anwendung, die C# verwendet .Net-Implementierung von substring viele zig-mal in einer Sekunde. Das brachte mich zum nachdenken...
- Gibt es Speicher Probleme mit der C# (.Net)
string.Substring
? - Was ist die Leistung wie auf
string.Substring
? Gibt es einen schnelleren Weg, um split einen string basierend auf start/end-position?
- 50 mal pro minute scheint kaum wie eine schwere Last auf mir. Hunderte zu den tausenden Zeiten pro Sekunde wäre heftig, aber einmal pro Sekunde und ein bisschen?
- Recht jetzt seinen einmal eine Sekunde, aber als die server-Belastung steigt, so steigt auch die Verwendung von substring.
- Der Punkt ist nicht, dass die CPU-Auslastung sehr hoch sein würde - wenn es eine server-Anwendung ausgeführt wird, die für viele Tage und den Aufruf Substring auf langen Saiten, könnte es noch 'Leck' eine Menge von Speicher über die Zeit, wenn .NET leidet unter dem gleichen problem.
- es war Ihre zweite Frage, über die ein schneller Weg, um eine Teilzeichenfolge, die ich kommentierte. Ein Speicherleck ist ein problem, das einen Blick Wert ist, sondern einen Kern-Frameworks wie
.Substring
sollte wohl angenommen werden, performant, bis Sie sehen, dass die eigentliche Verlangsamungen, dass Sie dann die Spur für diesen Vorgang. - Diese Frage wurde beantwortet von Eric Lippert selbst: stackoverflow.com/questions/2473816/...
- Der link zu dem Artikel mit dem Titel " Die Gefahren des String.substring " auf NFlath.com ist nicht mehr gültig.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Betrachten .NET ist die Implementierung von String.Substring, substring-nicht teilen-Speicher mit dem originalen.
Jedes mal, wenn Sie substring erstellen Sie eine neue string-Instanz - es muss kopieren Sie die Zeichen aus dem alten string der neue, zusammen mit der damit verbundenen neuen Speicher-Allokation und — nicht vergessen, dass diese unicode-Zeichen. Dies kann oder kann nicht eine schlechte Sache sein - einige zeigen Sie wollen diese Zeichen irgendwo sowieso. Je nachdem, was Sie tun, möchten Sie vielleicht Ihre eigene Methode, die bloß findet den richtigen Indizes innerhalb der Zeichenfolge, die Sie später verwenden können.
es ist immer gut zu versuchen, es & Messen der verstrichenen Millisekunden.
Im Falle des Java memory leak kann man erleben, wenn mit subString, es ist leicht behoben werden durch die Instanziierung ein neues String-Objekt mit dem copy-Konstruktor (d.h. einen Aufruf der form", new String(String)"). Mit diesem können Sie verwerfen alle Verweise auf das original (und in dem Fall, dass dies tatsächlich ein Problem, eher großen) String, und halten nur die Teile, müssen Sie es im Speicher.
Nicht ideal, in der Theorie der JVM könnte schlauer sein, und komprimieren Sie den String-Objekt (wie oben vorgeschlagen), aber das bekommt den job getan mit dem, was wir jetzt haben.
Als für C#, wie bereits gesagt wurde, ist dieses problem nicht vorhanden.
Nur um eine andere Perspektive auf dieses.
Out of memory (die meisten Male), bedeutet nicht, Sie haben alle die Erinnerung. Es bedeutet, dass Ihr Arbeitsspeicher fragmentiert wurde und die nächste Zeit, die Sie zuordnen wollen, ein Stück, das system ist nicht in der Lage zu finden, die einen zusammenhängenden Speicherblock, um Ihre Bedürfnisse anzupassen.
Häufigen Zuweisungen/deallocations wird die Ursache der Fragmentierung des Speichers. Die GC möglicherweise nicht in der Lage sein, zu de-fragment in die Zeit verklagen, um die Arten von Operationen, die Sie tun. Ich weiß der Server, GC in .NET ist ziemlich gut über die de-Fragmentierung der Erinnerung, aber Sie konnte immer verhungern (Verhinderung der GC zu tun, hol -) system, durch das schreiben schlechten code.
Die CLR (also C#'s) die Umsetzung der
Substring
nicht, behalten Sie einen Verweis auf die Quell-Zeichenfolge, so dass es nicht über die "memory leak" problem der Java-strings.die meisten dieser Art von string-Probleme sind da Strings unveränderlich ist. Die StringBuilder-Klasse ist gedacht für, wenn Sie tun eine Menge von string-Manipulationen:
http://msdn.microsoft.com/en-us/library/2839d5h5(VS.71).aspx
Beachten Sie, dass das eigentliche Problem ist der Speicher-Allokation statt der CPU, obwohl der übermäßige Speicher alloc braucht CPU...
Ich scheine zu erinnern, dass die strings in Java gespeichert wurden, als die tatsächlichen Zeichen zusammen mit einer start-und Länge.
Dies bedeutet, dass ein substring von string teilen können die gleichen Zeichen (da Sie unveränderlich), und pflegen nur noch eine separate start-und Länge.
So, ich bin mir nicht ganz sicher, was dein Speicher Probleme mit dem Java-strings.
Bezug auf das Artikel veröffentlicht in der Bearbeitung, es scheint ein bisschen ein Problem für mich.
Wenn Sie in der Gewohnheit riesige Saiten, dann mit einem kleinen Teilstring des Sie und so dass diejenigen, die herumliegen, wird dies von nahezu null Auswirkungen auf das Gedächtnis.
Selbst, wenn Sie hatte eine 10M Schnur und Sie machte 400 Teilzeichenfolgen ist, werden Sie nur mit, dass 10M für die zugrunde liegenden char-array - es ist nicht 400 Exemplare von diesem Teilstring. Die einzige Erinnerung Auswirkungen der start - /Länge bit jedes substring Objekt.
Des Autors scheint zu sein, beschweren sich, dass Sie Lesen eine riesige Zeichenfolge in den Speicher nur dann wollte es ein bißchen, aber die ganze Sache war gehalten - mein Vorschlag wäre, Sie vielleicht möchten zu überdenken, wie Sie Ihre Daten ein 🙂
Zu nennen, das ein Java-bug ist eine riesige Strecke, die so gut. Ein bug ist etwas das nicht funktioniert Spezifikation. Dies war ein bewusste design-Entscheidung, um die Leistung zu verbessern, Speicher erschöpft, weil Sie nicht verstehen, wie die Dinge funktionieren, ist kein Fehler, IMNSHO. Und es ist definitiv nicht ein Speicher-Leck.
Es wurde eine möglich guten Vorschlag in die Kommentare zu diesem Artikel, dass der GC konnte mehr aggressiv erholen bits der unbenutzte strings, die durch das zusammenpressen von Ihnen.
Dies ist nicht etwas, das Sie wollen, um zu tun, auf einer first-pass-GC, da wäre es relativ teuer. Jedoch, wo alle anderen GC operation versäumt hatte, zurückfordern, genug Platz, man könnte es tun.
Leider es würde mit ziemlicher Sicherheit bedeuten, dass die zugrunde liegenden
char
array brauchen würde, um zu halten eine Aufzeichnung aller string-Objekte, die referenziert werden, so könnte es sowohl herauszufinden, was die bits wurden nicht verwendete und ändern Sie den string-Objekt start-und length-Felder.Diese in sich selbst einführen kann unannehmbaren Auswirkungen auf die Leistung und, oben auf, dass, wenn Ihr Gedächtnis ist so kurz das dies ein problem, können Sie nicht einmal in der Lage sein, genügend Platz für eine kleinere version der Zeichenfolge.
Ich denke, wenn der Speicher ausgeht, würde ich wahrscheinlich lieber nicht werden die Pflege dieses char-array-auf-string mapping, um dieses Niveau der GC möglich, stattdessen würde ich es bevorzugen, dass der Speicher verwendet werden, für meine Zeichenfolgen.
Da es eine vollkommen akzeptable Problemumgehung, und gute Programmierer sollte wissen über die Schwächen Ihrer Sprache der Wahl, ich vermute, der Autor hat Recht - es nicht behoben werden.
Nicht, weil die Java-Entwickler zu faul sind, sondern weil es ist nicht ein problem.
Du bist frei, um Ihre eigenen string-Methoden, die mit dem C# - ones (die teilen aber nicht die zugrunde liegenden Daten werden, außer in bestimmten Szenarien). Dies löst Ihre Probleme mit dem Speicher aber auf Kosten von Leistungseinbußen, da müssen Sie kopieren die Daten bei jedem Aufruf substring. Wie bei den meisten Dingen in der IT (und das Leben), es ist ein trade-off.
Returns a new string that is a substring of this string
. Es gibt keinen Hinweis, dass die zurückgegebene Zeichenfolge ist die Belegung der original-Strings im Speicher. Also die docs sollten entweder klar auf die tatsächliche Verhalten oder diese "Optimierung" sollte sein vermied. Es ist Ihre Wahl - entweder die docs ist fehlerhaft oder die Umsetzung ist. Entwickler sollten sich nicht haben zu prüfen, die interne Implementierung dieser Methoden zu verstehen, wie man Sie richtig zu verwenden.Zur Profilierung Speicher während der Entwicklung können Sie diesen code verwenden:
Über parameter forceFullCollection: "Wenn die forceFullCollection parameter true ist, wird diese Methode wartet eine kurzen Pause vor der Rückkehr, während das system sammelt Müll und Finalisiert Objekte. Die Dauer des Intervalls ist eine intern festgelegte limit bestimmt durch die Anzahl der garbage collection-Zyklen abgeschlossen ist und die Veränderung in der Menge an Speicher zurückgewonnen zwischen den Zyklen. Der garbage collector nicht garantieren, dass alle unzugänglich Speicher gesammelt wird." GC.GetTotalMemory Methode
Glück!;)