int.toString() sehr langsam,was kann ich tun?
-
ok ich hab mich mal selber an einer Konvertierung versucht...
aber ich glaube mir fehlen da paar Gehirnwindungen um es effektiv
hinzubekommen. Meine Implementierung ist ungefähr 20000 mal langsamerpublic static int GetLengthInt(int zahl) { return (zahl > 0) ? 1 + GetLengthInt((int)(zahl * 0.1)) : 0; } public static string myToString(int pi) { int iLen = GetLengthInt(pi); char[] cChArray = new char[iLen]; int iCurZahl = pi; double dBasis; for (int i = (iLen - 1); i >= 0; i--) { dBasis = 1 / Math.Pow(10, i); iCurZahl = (int)(iCurZahl * dBasis); cChArray[i] = (char)(iCurZahl + 48); } StringBuilder tsb = new StringBuilder(); for (int i = (iLen - 1); i >= 0; i--) tsb.Append(cChArray[i]); return tsb.ToString(); } }
-
Aus Erfahrung sollte ein
ieht man im Codeausschnitt nicht, daher: ListView.BeginUpdate und ListView.Endupdate verwenden. (Ausserhalb der foreach)
reichen. (Es sei denn man hat das 1.0er CF, dann hat man einfach pech gehabt.)
-
Das der Code langsam ist @Nahasapeemapetilon glaub ich gern.
-
wie ist die performance im vergleich ?
a) int.ToString();
b) Convert.ToString(int);
c) string.Format("{0}", int);??
-
Mr Evil schrieb:
wie ist die performance im vergleich ?
a) int.ToString();
b) Convert.ToString(int);
c) string.Format("{0}", int);??
String.Format ist nahezu immer die langsamste, dafür sicherste Alternative...
Beide andere Implementierungen kommen nicht an dme Problem vorbei das zur Umwandlung von int nach String divisionen gebraucht werden (mindestens eine Division pro Stelle). Auf unseren mit FPUs verwöhnten Desktopkisten ist das kein Thema, auf einem mobile wohl schon eher.
-
@Nahasapeemapetilon:
Bist du sicher dass es an der ToString Funktion liegt?
Kannst du bitte den exakten Code posten der bei dir fast doppelt so schnell läuft?
-
David_pb schrieb:
Das der Code langsam ist @Nahasapeemapetilon glaub ich gern.
jo in der Mittagspause schnell zurecht zusammen geflickert
...für Verbesserungen bin ich offen!
Mr Evil schrieb:
wie ist die performance im vergleich ?
a) int.ToString();
b) Convert.ToString(int);
c) string.Format("{0}", int);??
ich hab mal nen kleines Preformance-tool gebastelt
um die einzelnen unterschiede zu ermitteln:public static void Main(string[] args) { System.Globalization.NumberFormatInfo n = System.Globalization.CultureInfo.InvariantCulture.NumberFormat; const int iDurch = 40; for (int k = 0; k <= 5; k++) { int[] tTicks = new int[iDurch]; for (int b = 0; b < iDurch; b++) { int start = Environment.TickCount; string conv; for (int i = 5000; i < 3000000; i++) { switch (k) { case 0: conv = i.ToString(); break; case 1: conv = i.ToString(n); break; case 2: conv = Convert.ToString(i); break; case 3: conv = Convert.ToString(i, n); break; case 4: conv = string.Format("{0}", i); break; case 5: conv = myToString(i); break; default: break; } } tTicks[b] = Environment.TickCount - start; } int sum = 0; foreach (int z in tTicks) sum += z; switch (k) { case 0: Console.Out.WriteLine("toString:" + sum / iDurch); break; case 1: Console.Out.WriteLine("toString n:" + sum / iDurch); break; case 2: Console.Out.WriteLine("convert" + sum / iDurch); break; case 3: Console.Out.WriteLine("convert n:" + sum / iDurch); break; case 4: Console.Out.WriteLine("format:" + sum / iDurch); break; case 5: Console.Out.WriteLine("mytostring" + sum / iDurch); break; default: break; } } Console.In.Read(); }
mit folgenden output:
toString: 981
toString n: 960
convert 1017
convert n: 941
format: 1934
mytostring 4311 oh man
-
@Nahasapeemapetilon: dein Vergleich ist IMO total uninteressant, da im Original-Code Dinge drinnen sind die vermutlich viel viel länger dauern als ein Int64.ToString().
z.B. das Einfügen der ListView Items. EDIT: oder das Erzeugen/Initialisieren der ganzen FileInfo Objekte. /EDIT
Daher glaube ich auch nicht dass es am ToString() liegt dass der Code ohne ToString() so viel schneller ist. Sondern z.B. daran dass du (mutmasslich) beim Code ohne ToString(), auch nur ein ListView Item einfügst. Oder die FileInfo.Length Property nicht ausliest. Wenn die z.B. lazy evaluiert wird kann das einen grossen Unterschied machen. Oder...
Vergleiche mal
start = Environment.TickCount; System.Globalization.NumberFormatInfo n = System.Globalization.CultureInfo.InvariantCulture.NumberFormat; string[] tStringA = new string[2]; foreach (string tFile in tFiles) { tInfo = new FileInfo(tFile); tStringA[0] = tInfo.Name; tStringA[1] = tInfo.Length.ToString(n); listView1.Items.Add(new ListViewItem(tStringA)); } MessageBox.Show((Environment.TickCount-start).ToString());
mit
start = Environment.TickCount; System.Globalization.NumberFormatInfo n = System.Globalization.CultureInfo.InvariantCulture.NumberFormat; string[] tStringA = new string[2]; Int64 dummy = 0; foreach (string tFile in tFiles) { tInfo = new FileInfo(tFile); tStringA[0] = tInfo.Name; // tStringA[1] = tInfo.Length.ToString(n); dummy += tInfo.Length; tStringA[1] = "test"; listView1.Items.Add(new ListViewItem(tStringA)); } MessageBox.Show((Environment.TickCount-start).ToString() + " (dummy = " + dummy.ToString() + ")");
Vermutlich werden die zwei Versionen fast gleich schnell laufen. Falls das so ist wäre meine Vermutung bestätigt, nämlich dass es nicht an Int64.ToString() liegt.
BTW: die "dummy" Variable (inklusive der Ausgabe des finalen Werts in der MessageBox) ist eine einfache Möglichkeit sicherzustellen, dass der Aufruf von tInfo.Length nicht wegoptimiert werden kann.
-
Zur Info:
o Convert.ToString( int ) nutzt für Integer einfach value.ToString()
o String.Format verwendet intern nen Stringbuilder, der viel zu viel Aufwand betreibt.Du hast also keinen Vorteil, außer ggf weitere Funktionsaufrufe.
-
hustbaer schrieb:
@Nahasapeemapetilon: dein Vergleich ist IMO total uninteressant, da im Original-Code Dinge drinnen sind die vermutlich viel viel länger dauern als ein Int64.ToString().
Hi, danke für die Antwort! Das der Vergleich im Bezug auf mein Original Code nicht relevant ist war mir schon klar, ich wollte nur mal testen wie lange die Unterschiedlichen toString-Funktionen überhaupt brauchen bzw. welche schneller oder langsamer ist.
hustbaer schrieb:
@Nahasapeemapetilon:Vermutlich werden die zwei Versionen fast gleich schnell laufen. Falls das so ist wäre meine Vermutung bestätigt, nämlich dass es nicht an Int64.ToString() liegt.
Und zu deiner 2 Vermutung hast,da du voll ins Schwarze getroffen
ich hatte vorher zwar auch so was ähnliches getestet allerdings:....tStringA[1] = "50";...
Das war allerdings net so schlau, weil ich davon ausgegangen bin, dass die Length in den Info Objekt schon als Wert vorliegt und nicht noch irgendwie berechnet werden muss.
Naja wieder eine Erfahrung reicher
Nichtsdestotrotz, wenn irgendjemand vielleicht noch mal Lust verspürt die myToString()
zu optimieren kann er das ja mal tun. Am besten mit Begründung warum die Änderungen erfolgt sind und weshalb sie Performanter sind...da mit ich noch bisschen was dazu lerne
lg