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



BeitragVerfasst: Sa 30.04.11 10:18 
habe hier eine verständniss frage zum thema speicheraloc. - verwaltung von string und stringbuilder klassen.



wenn ich zb.:

string text = "hallo" oder string text = new String("hallo") ;zuweise wird hier nur die referenz von der zeichenfolge "hallo" gespeichert oder wird von seitens stringklasse speicher angefordert und der string kopiert ?

wenn speicher angefordert wird ,wird vorher geprüft ob die zeichenkette in dehm alten angeforderten speicher passt oder wird komplet neuer speicher angefordert ?

wie funktioniert stringbuilder diesbezüglich ?


da ich zur zeit vor der frage stehe welcher kontext passen würde


(ausszug aus dehm betrefenden code)

ausblenden 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:
  stringbuilder txt2;
  
     txt2 = new StringBuilder(NewSurfaceList[x].TexturName2);
          if (txt2.Length != 0)
                  fs.WriteLine("  texture2Name  = \"{0}\",", txt2.ToString() );
                          
     txt2 = new StringBuilder(NewSurfaceList[x].TexturName3);
           if (txt2.Length != 0)
                   fs.WriteLine("  texture3Name  = \"{0}\",", txt2.ToString() );

                    StringBuilder txt1 = new StringBuilder(NewSurfaceList[x].flags[0]);

                                for (UInt32 x1 = 1; x1 < 8; x1++)
                                {
                                    txt2  = new StringBuilder(NewSurfaceList[x].flags[x1]);

                                    if (txt2.Length != 0 )
                                    {
                                        txt1.AppendFormat(" + {0}", txt2.ToString() );
                                    }
                                    else
                                    {
                                        fs.WriteLine("  flags\t        =  {0},", txt1.ToString() );
                                        break;
                                    }
                                }


oder würde das eher passen ??

ausblenden 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:
  string txt2;
  
     txt2 = NewSurfaceList[x].TexturName2;

          if (txt2 != null)
                  fs.WriteLine("  texture2Name  = \"{0}\",", txt2 );
                               
     txt2 = NewSurfaceList[x].TexturName3;
           if (txt2 != null)
                   fs.WriteLine("  texture3Name  = \"{0}\",", txt2 );

                    StringBuilder txt1 = new StringBuilder(NewSurfaceList[x].flags[0]);
                    
                    stringbuilder txt3;

                                for (UInt32 x1 = 1; x1 < 8; x1++)
                                {
                                    txt3  = new StringBuilder(NewSurfaceList[x].flags[x1]);

                                    if (txt3.Length != 0 )
                                    {
                                        txt1.AppendFormat(" + {0}", txt3.ToString() );
                                    }
                                    else
                                    {
                                        fs.WriteLine("  flags\t        =  {0},", txt1.ToString() );
                                        break;
                                    }
                                }


oder gar so ??

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
     
          if (NewSurfaceList[x].TexturName2 != null)
                  fs.WriteLine("  texture2Name  = \"{0}\",", NewSurfaceList[x].TexturName2 );

           if (NewSurfaceList[x].TexturName3 != null)
                   fs.WriteLine("  texture3Name  = \"{0}\",", NewSurfaceList[x].TexturName3 );

                    StringBuilder txt1 = new StringBuilder(NewSurfaceList[x].flags[0]);

                                for (UInt32 x1 = 1; x1 < 8; x1++)
                                {
                                    if (NewSurfaceList[x].flags[x1] != null )
                                    {
                                        txt1.AppendFormat(" + {0}", NewSurfaceList[x].flags[x1] );
                                    }
                                    else
                                    {
                                        fs.WriteLine("  flags\t        =  {0},", txt1.ToString() );
                                        break;
                                    }
                                }


ich muss dazu sagen das die gesamtroutine ,in die der code eingebettet ist ,bis zu 1000 -5000 mal aufgerufen wird

ich hoffe jemand kann licht ins dunkeln bringen

mfg nuckey

Moderiert von user profile iconChristian S.: Code- durch C#-Tags ersetzt


Zuletzt bearbeitet von Nuckey am Sa 30.04.11 11:01, insgesamt 1-mal bearbeitet
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4807
Erhaltene Danke: 1061

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Sa 30.04.11 10:40 
Hallo nuckey,

könntest du noch mal deinen Beitrag editieren und die überflüssigen Leerzeilen (und Leerzeichen am Anfang der Zeilen) aus deinem Code entfernen? (Da ich so nicht die Unterschiede zwischen den drei Versionen erkennen kann.)

Einen StringBuilder kannst du dir wie einen selbstwachsenden Puffer vorstellen, welcher im voraus Speicher alloziert und erst bei Überschreiten dieser Grenze genug neuen Speicher alloziert (und dann den alten Inhalt kopiert). Meistens wird eine Verdoppelungsstrategie gewählt (Falls du C++ kannst, dann verhält es sich so ähnlich wie mit der std::vector<>-Klasse).
Bei reinen Stringzuweisungen und -additionen wird immer ein neuer String erstellt und dann die alten Zeichen hineinkopiert.
Nuckey Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 78



BeitragVerfasst: Sa 30.04.11 11:12 
hio th69

bin dein wunsch nachgekommen und habe ein paar leerzeilen gelöcht ;)

also versteh ich dich richtig,da bei direkter zuweisung (= "bla" oder new String("bla") ),
die stringklasse generell speicher neu anfordert ?

na ja aber wie handhabt es die stringbuilderklasse bei neu zuweisungen ?

zb stringbuilder text = new Stringbuilder("bla");

da hier eigentlich eine neue instanz der klasse gebildet wird und zu gewiesen

in der schleife wäre stringbuilderklasse besser aufgehoben (in allen 3 varianten)

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
            StringBuilder txt1 = new StringBuilder(NewSurfaceList[x].flags[0]);

                                for (UInt32 x1 = 1; x1 < 8; x1++)
                                {
                                    if (NewSurfaceList[x].flags[x1] != null )
                                    {
                                        txt1.AppendFormat(" + {0}", NewSurfaceList[x].flags[x1] );
                                    }
                                    else
                                    {
                                        fs.WriteLine("  flags\t        =  {0},", txt1.ToString() );
                                        break;
                                    }
                                }


wie ich schon schrieb wird die methode ungef. 1000 - 5000 oder höher aufgerufen und da wäre eine speicherschonende variante schon angebracht.

(deswegen die 3 varianten ,des code auszugs)


mfg nuckey

Moderiert von user profile iconChristian S.: Code- durch C#-Tags ersetzt
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4807
Erhaltene Danke: 1061

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Sa 30.04.11 13:35 
Hallo nuckey,

ok, so kann ich es schon besser lesen (und vergleichen ;-)).

Die 1. Variante ist jedenfalls Unsinn, d.h. das Erzeugen eines StringBuilders, nur um dessen Wert wieder auszulesen (die ersten drei Zeilen des Codes).
Gleiches gilt dann für die 2. Variante (mit 'txt3' innerhalb deiner Schleife).
Daher ist nur die 3. Variante zu empfehlen!

Ein StringBuilder lohnt sich (performance-technisch) nur, wenn du viele String-Additionen (Konkatenationen) durchführst, benötigt aber (temporär) eben ein bißchen mehr Speicher.

Ab .NET 4 gibt es auch die StringBuilder.Clear()-Methode, um innerhalb einer (äußeren) Schleife nicht immer wieder eine neue StringBuilder-Instanz erzeugen zu müssen (bzw. dessen Length-Eigenschaft auf 0 zu setzen).

Du kannst dir ja mal testweise die Eigenschaften 'Length' und 'Capacity' innerhalb der StringBuilder-Schleife ausgeben lassen (um den Unterschied zu sehen).
Nuckey Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 78



BeitragVerfasst: Sa 30.04.11 14:29 
danke th69

dehn gedanken mit dehn stringbuilder hatte ich ,da ich jedesmal mit new zuweise und um adressoperationen zu minimieren

(in c/c++) hätte ich es etwas anders gestaltet ,direkt referenz auf einem zeiger;

aber gut da muss ich mich noch ein bischen mit c# und seine eigenheiten beschäftigen.hast ja einige links ,im anderen thread gepostet mal sehen was die übersetzung bringt ;)

und mir der clear methode werd ich gleich mal ausprobieren,denn irgenwie stören mich viele new anweisungen,auf hinblick der speicherperformance und der hohen anzahl der aufrufe der hauptmethode.


mfg nuckey