Autor Beitrag
Nuckey
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 78



BeitragVerfasst: 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:
ausblenden 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());

// oder direkt.     

     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 user profile iconTh69: Code- durch C#-Tags ersetzt
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4798
Erhaltene Danke: 1059

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 78



BeitragVerfasst: 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
ausblenden volle Höhe C#-Quelltext
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)
ausblenden volle Höhe C#-Quelltext
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 user profile iconChristian S.: Code- durch C#-Tags ersetzt
Yogu
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2598
Erhaltene Danke: 156

Ubuntu 13.04, Win 7
C# (VS 2013)
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 78



BeitragVerfasst: 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?
ausblenden 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
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
Autoflush = false;

public void write(StreamWriter sw)
{
  sw.Write
  .
  .
  .
  flush();
}


mfg nuckey
Yogu
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2598
Erhaltene Danke: 156

Ubuntu 13.04, Win 7
C# (VS 2013)
BeitragVerfasst: So 15.04.12 15:42 
user profile iconNuckey hat folgendes geschrieben Zum zitierten Posting springen:
mit tcp/p hat es nix zu tun ;)

Hups, ich da habe ich von meinem eigenen Projekt auf deines geschlossen ;)

Dann geht's wohl um einen Dateizugriff? In diesem Fall kann es sein, dass das manuelle Flushen gar nichts mehr bringt, da das Betriebssystem Dateizugriffe ohnehin optimiert. Ich kann mir gut vorstellen, dass da erstmal in den Arbeitsspeicher geschrieben wird und nur hin und wieder, vor allem eben beim Schließen der Festplattenzugriff erfolgt. Ist aber nur eine Vermutung.

user profile iconNuckey hat folgendes geschrieben Zum zitierten Posting springen:
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.

Dann wird Flush implizit aufgerufen:

Aus MSDN:
Wenn AutoFlush auf false festgelegt wird, führt StreamWriter eine beschränkte Pufferung intern [...] aus.


user profile iconNuckey hat folgendes geschrieben Zum zitierten Posting springen:
wie schon beschrieben möchte ich so wenig an speicher verschwenden ,denn es werden bis zu 50000 objecte angelegt und geschrieben.

Dann würde ich - wie ich es ja bereits getan habe ;) - vom StringBuilder abraten. Der würde nämlich die Daten durch eine weitere Speicherzelle schliefen.

user profile iconNuckey hat folgendes geschrieben Zum zitierten Posting springen:
bei verwendung der using direktive müsste das schreiben automatisch geschehen oder?
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
using(StreamWriter sw = new ....)
{
  sw.AutoFlush = false;


  sw.Writeline....
  .
  .
} hier müste autom. close erfolgen und somit auch das schreiben

oder
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
Autoflush = false;

public void write(StreamWriter sw)
{
  sw.Write
  .
  .
  .
  flush();
}

Beide Quelltexte werden korrekt flushen.

Grüße,
Yogu
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 78



BeitragVerfasst: Mo 16.04.12 19:38 
danke euch .

der stream wird per using anweisung geöffnet/geschlossen.

die writemethode wird jetz so aufgerufen
ausblenden 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