Autor |
Beitrag |
Nuckey
      
Beiträge: 78
|
Verfasst: Sa 14.04.12 14:19
zur zeit schwirt ein problem/frage in meinem kopf rum.
wenn ich mit stringbuilder arbeite nimmt dieser je nach grösse der strings speicher in anspruch,
ebenso StreamWriter (glaube von 1024byte).
was wäre speicher schonender:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| StringBuilder sb = new StringBuilder(); sb.append("hallo"); . viele strings . sb.append("welt");
StreamWriter sw .... sw.Writeline(sb.tostring());
sw.writeline("hallo"); . viele strings . sw.writeline("welt"); |
mit viele strings meinte ich,das da nicht nur mit 2 stringketten gearbeitet wird zb. mit 20.
ist es "wirtschaftlicher" von einem buffer in dehn anderen zu schreiben oder
direkt ?.
mfg nuckey
Moderiert von Th69: Code- durch C#-Tags ersetzt
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Sa 14.04.12 14:59
Von deinem Casing und Methodenbezeichnung her soll, das wirklich C# sein oder eher Java?
In .Net hat ein Stringbuilder eine DefaultKapazität von 16 Chars (nicht zu verwechseln mit 16 Byte) und verdoppelt die Größe bei Bedarf.
Wenn du nach Wirtschaftlichkeit fragst müsste ich antworten die Version du du schneller fehlerfrei entwickeln kannst. Der eventuelle Unterschied in der Ausführungsgeschwindigkeit ist in 99,99% aller Anwendungsfälle kosten technisch vernachlässigbar gegenüber den Entwicklungskosten.
Wenn die Frage auf die Ausführungsgeschwindigkeit abzielte würde ich die erste Version vorziehen da ich die Geschwindigkeit für vorhersagbarer halte. Bei der direkte Nutzung des Streamwriters kommt es auf das genaue Verhalten des dahinterliegenden Streams an. Wie oft zwischendurch vom Streamwriter geflusht wird und wie performant der Flush ist. Wenn du den StringBuilder schon mit passender Kapazität initialisiert hast bleiben als die zwei treibenden Kostenfaktoren nur der ToString und das nur einmalige flushen über den Streamwriter. Das unter der Annahme das StringBuilder.Append und StreamWriter.Write (ohne einen eventuellen Flush in Write) etwa gleich schnell sein werden.
|
|
Th69
      

Beiträge: 4798
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Sa 14.04.12 15:00
Hallo Nuckey,
bei dem StreamWriter ist es eigentlich unsinnig, zuerst einen StringBuilder zu benutzen, um daraus dann einen String zu erzeugen, welcher dann gestreamt wird.
Sinn könnte dies höchstens machen, wenn man eine externe Methode verwendet, welche den Inhalt erzeugen soll. Dann würde man wohl besser einen String zurückgeben, anstatt direkt in einen Stream zu schreiben (damit diese Methode allgemeingültig bleibt).
|
|
Nuckey 
      
Beiträge: 78
|
Verfasst: Sa 14.04.12 18:19
danke erstmal:
nein ralf es ist nicht java, eher pseudo-pseudo c#++
es ist so das ich bisher die felser ausgelesenhabe und dies in einem string per stringbuilder gepacckt habe
und diese den per stream geschrieben habe.
beispiel
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50:
| public class Klasse stringbuilder sb = new stringbuilder
public ToString() { sb.Clear(); sb.AppendLine("newBlueprint = {");
if (!S2EdParseCtrl.IsString(this._s2ObjectInfo)) sb.AppendFormat("--# {0}\r\n", this._s2ObjectInfo);
sb.AppendFormat(" id = {0},\r\n", this._s2ObjectId); sb.AppendFormat(" name = \"{0}\",\r\n", this._s2ObjectName); sb.AppendFormat(" palettebits = \"{0}\",\r\n", this._palettebits); sb.AppendFormat(" dmgvariation = {0},\r\n", this._dmgvariation); sb.Append(this.MinConStraints.ToString()); sb.AppendFormat(" lvljump = {0},\r\n", this._lvljump); sb.AppendFormat(" usability = {0},\r\n", this._usability); sb.Append(this.AllotmentPmfpi.ToString());
if (!S2EdParseCtrl.IsString(this._unicname)) sb.AppendFormat(" uniquename = \"{0}\",\r\n", this._unicname);
sb.AppendFormat(" specialuseonly = {0},\r\n", this._specialuseonly);
if (_BonusGroupList.Count > 0) { foreach (S2EdBlPrBonusGroup obj in _BonusGroupList) { sb.Append(obj.ToString()); } }
if (!S2EdParseCtrl.IsString(this._itemtypes)) sb.AppendFormat(" itemtypes = {{{0}}},\r\n", this._itemtypes);
if (!S2EdParseCtrl.IsString(this._wearergroups)) sb.AppendFormat(" wearergroups = {{\'{0}\',}},\r\n", this._wearergroups);
sb.AppendFormat("}}\r\nmgr.createBlueprint({0}, newBlueprint);\r\n", this._s2ObjectId); return sb.ToString(); }
#irgenwo
streamwriter sw = new ........
sw.Writeline(s2object.ToString() ); |
also schon menge strings die da reingepackt werden
das gegenstück (mein favorit)
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37:
| public override void Write(StreamWriter sw) { sw.WriteLine("newBlueprint = {");
if (S2EdParseCtrl.IsString(this._s2ObjectInfo) == true) sw.WriteLine("--# {0}", this._s2ObjectInfo);
sw.WriteLine(" id = {0},", this._s2ObjectId); sw.WriteLine(" name = \"{0}\",", this._s2ObjectName); sw.WriteLine(" palettebits = \"{0}\",", this._palettebits); sw.WriteLine(" dmgvariation = {0},", this._dmgvariation); this.MinConStraints.Write(sw); sw.WriteLine(" lvljump = {0},", this._lvljump); sw.WriteLine(" usability = {0},", this._usability); this.AllotmentPmfpi.Write(sw);
if (!S2EdParseCtrl.IsString(this._unicname)) sw.WriteLine(" uniquename = \"{0}\",", this._unicname);
sw.WriteLine(" specialuseonly = {0},", this._specialuseonly);
if (_BonusGroupList.Count > 0) { foreach (S2EdBlPrBonusGroup obj in _BonusGroupList) { obj.Write(sw); } }
if (!S2EdParseCtrl.IsString(this._itemtypes)) sw.WriteLine(" itemtypes = {{{0},}},", this._itemtypes);
if (!S2EdParseCtrl.IsString(this._wearergroups)) sw.WriteLine(" wearergroups = {{\'{0}\',}},", this._wearergroups);
sw.WriteLine("}}\nmgr.createBlueprint({0}, newBlueprint);\n", this._s2ObjectId); } |
das letztere sagt mir mein bauchgefühl ist vom speichermanagment besser ,da ich die daten direkt in dehn streambuffer schreibe (glaub ich zumindenst)
mfg nuckey, this._s2ObjectName);
sw.WriteLine(
Moderiert von Christian S.: Code- durch C#-Tags ersetzt
|
|
Yogu
      
Beiträge: 2598
Erhaltene Danke: 156
Ubuntu 13.04, Win 7
C# (VS 2013)
|
Verfasst: Sa 14.04.12 18:30
Hallo,
dein Beispiel mit dem StringBuilder sieht so unübersichtlich aus, dass ich davon abraten würde. Ich könnte mir gut vorstellen, dass ich bei so etwas schnell mal ein \r oder \n vergessen würde.
Am effizientesten wäre es wohl, direkt in den StreamWriter zu schreiben, allerdings AutoFlush auf false zu setzen und am Ende der Methode Flush aufzurufen. Dann landen alle Daten direkt im Writer-Buffer, werden also nicht doppelt gepuffert, was ja zusätzliche Datenverschiebungen mit sich ziehen würden. Das manuelle Flushen sorgt dafür, dass die Paketgröße des Streams ausgenutzt wird und nicht für jede kurze Zeile ein eigenes TCP/IP-Paket losgeschickt wird.
Grüße,
Yogu
|
|
Nuckey 
      
Beiträge: 78
|
Verfasst: Sa 14.04.12 18:44
hi yogu:
danke für dehn tip.
mit tcp/p hat es nix zu tun
wie ist das verhalten von streamwriter wenn das stringpacket grösser ist als der interne buffer ??
soweit ich es weiss ist dieser auf 1024 begrenzt.
wie schon beschrieben möchte ich so wenig an speicher verschwenden ,denn es werden bis zu 50000 objecte angelegt und geschrieben.
bei verwendung der using direktive müsste das schreiben automatisch geschehen oder?
Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| using(StreamWriter sw = new ....) { sw.AutoFlush = false;
sw.Writeline.... . . } hier müste autom. close erfolgen und somit auch das schreiben |
oder
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| Autoflush = false;
public void write(StreamWriter sw) { sw.Write . . . flush(); } |
mfg nuckey
|
|
Yogu
      
Beiträge: 2598
Erhaltene Danke: 156
Ubuntu 13.04, Win 7
C# (VS 2013)
|
Verfasst: So 15.04.12 15:42
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: So 15.04.12 16:56
Zitat: | soweit ich es weiss ist dieser auf 1024 begrenzt. |
Kommt drauf an. Wenn du einen der Konstruktoren mit Path benutzt hast wird der StreamWriter einen eigenen Filestream erzeugen und einen 4K Buffer (übliche Sektorgröße einer Festplatte) benutzen. Wenn du einen selbst erzeugten Stream (auch wenn dieser ein Filestream ist) übergibst wird ein 1K Buffer verwendet. In beiden Fällen gilt das natürlich nur wenn du nicht selbst eine Puffergröße übergeben hast.
|
|
Nuckey 
      
Beiträge: 78
|
Verfasst: Mo 16.04.12 19:38
danke euch .
der stream wird per using anweisung geöffnet/geschlossen.
die writemethode wird jetz so aufgerufen
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| public void Write(StreamWriter sw) { sw.AutoFlush = false; sw.Write ... .... . . sw.Flush() } |
und mit dehm puffer zuweisen ist mir neu darüber steht nix in dehn buch.
zumindenst weiss ich jetz in welche richtung ich weiter suchen muss  .
danke nochmal
mfg nuckey
|
|
|