Entwickler-Ecke
Algorithmen, Optimierung und Assembler - Bytes in KB, MB,... schnell darstellen
AXMD - So 20.04.08 17:28
Titel: Bytes in KB, MB,... schnell darstellen
Hallo!
Ich arbeite momentan an einem Programm, das oft (mehrmals pro Sekunde) Zahlen formatieren muss, um genau zu sein soll eine Anzahl Bytes in einen String mit 3 Nachkommastellen konvertiert werden und die Präfixe K, M, G,... etc. angehängt werden. Folgenden Code habe ich bisher:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| public static string FormatBytes(long Bytes) { if (Bytes < 0) return "?"; char[] Prefixes = { 'K', 'M', 'G', 'T', 'P', 'E' }; int Prefix = -1; long TempBytes = Bytes; while ((TempBytes = (TempBytes >> 10)) != 0) Prefix++; if (Prefix == -1) return Bytes.ToString() + " Bytes"; else { long Total = Bytes >> ((Prefix + 1) * 10); long Fractal = (Bytes >> (Prefix * 10)) & 0x3FF; Fractal = (Fractal * 1000) >> 10; return Total.ToString() + System.Globalization.NumberFormatInfo.CurrentInfo.NumberDecimalSeparator + Fractal.ToString("000") + " " + Prefixes[Prefix].ToString() + "B"; } } |
Er ist schon um einiges schneller als eine while-Schleife mit float-Operationen, aber da könnte man doch bestimmt noch mehr optimieren, oder ;) ? Vor allem die Zeile
Fractal = (Fractal * 1000) >> 10; könnte man doch vielleicht ohne Multiplikation hinbekommen. Die Frage ist nur wie - die Genauigkeit sollte nicht spürbar leiden. Welche Optimierungspotenziale gibt es hier noch?
AXMD
Christian S. - Mo 21.04.08 10:43
Hi!
Anfangen würde ich damit, das Array nicht jedes Mal von Neuem zu definieren, sondern als readonly-Feld der Klasse zu machen. Auch könntest Du schauen, ob String.Format schneller ist, als eine String-"Addition".
Bist Du sicher, dass die Methode der Flaschenhals ist? Und macht das eigentlich Sinn, mehrmals die Sekunde einen Wert zu aktualisieren? :gruebel:
Grüße
Christian
BenBE - Mo 21.04.08 11:50
Ferner gilt auch für emulierte Sprachen auf virtuellen Maschinen: Vergleiche mit 0 sind schneller.
Was Du also machen solltest, ist ne Index-Verschiebung einzubauen, so dass Index 0 nen Leerstring enthält (B hat ja keinen Präfix).
Ferner solltest Du schauen, dass Du
Ki statt
K schreibst (ist "konformer").
Insgesamt würde dass dann so aussehen:
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:
| readonly char[] Prefixes = { 'K', 'M', 'G', 'T', 'P', 'E' }; public static string FormatBytes(long Bytes) { if (Bytes < 0) return "?"; int Prefix = 0; long TempBytes = Bytes; while ((TempBytes = (TempBytes >> 10)) != 0) Prefix++; if (0 == Prefix) return Bytes.ToString() + " Bytes"; else { long Total = Bytes >> ((Prefix) * 10); long Fractal = (Bytes >> ((Prefix - 1) * 10)) & 0x3FF; Fractal = (Fractal * 1000) >> 10; return Total.ToString() + System.Globalization.NumberFormatInfo.CurrentInfo.NumberDecimalSeparator + Fractal.ToString("000") + " " + Prefixes[Prefix].ToString() + "iB"; } } |
Ungetestet ...
HTH.
AXMD - Mo 21.04.08 13:23
Christian S. hat folgendes geschrieben: |
Bist Du sicher, dass die Methode der Flaschenhals ist? Und macht das eigentlich Sinn, mehrmals die Sekunde einen Wert zu aktualisieren? :gruebel: |
Die Methode ist kein Flaschenhals in dem Sinn - sie benötigt nur im Vergleich zu den anderen Aktualisierungsoperationen die meiste Zeit, da sie öfters aufgerufen wird.
BenBE hat folgendes geschrieben: |
Ferner gilt auch für emulierte Sprachen auf virtuellen Maschinen: Vergleiche mit 0 sind schneller.
Was Du also machen solltest, ist ne Index-Verschiebung einzubauen, so dass Index 0 nen Leerstring enthält (B hat ja keinen Präfix). |
Werd ich machen, das klingt sinnvoll. Allerdings hätt ich statt "B" gerne "Bytes" angezeigt - lässt sich das in diesem Konzept ohne viel Aufwand realisieren?
BenBE hat folgendes geschrieben: |
|
Mit 64 Bit lassen sich trotzdem keine 70 Bit darstellen, und die FileStreams in .NET liefern alle maximal 64-Bit-Längen bzw. -Positionen ;)
Danke erstmal für die Tipps, werde das integrieren und mir ansehen, wie sich die Laufzeit verändert.
AXMD
BenBE - Mo 21.04.08 13:34
AXMD hat folgendes geschrieben: |
BenBE hat folgendes geschrieben: | Ferner gilt auch für emulierte Sprachen auf virtuellen Maschinen: Vergleiche mit 0 sind schneller.
Was Du also machen solltest, ist ne Index-Verschiebung einzubauen, so dass Index 0 nen Leerstring enthält (B hat ja keinen Präfix). |
Werd ich machen, das klingt sinnvoll. Allerdings hätt ich statt "B" gerne "Bytes" angezeigt - lässt sich das in diesem Konzept ohne viel Aufwand realisieren? |
Siehe oben in meinem Beispiel, da hab ich das mal eben umgesetzt, hoffe, ich hab mich nicht vertan und soweit ale Vorkommen erwischt ...
Die Ausgabe Bytes statt B ist doch eigentlich nur hinten den String ändern, oder meinst Du Byte\Bytes je nach Präfix vorn?
Grob würd ich sagen:
C#-Quelltext
1:
| + ( (0 == fractal) && (1 == total) ? "Byte" : "Bytes"); |
AXMD hat folgendes geschrieben: |
BenBE hat folgendes geschrieben: | |
Mit 64 Bit lassen sich trotzdem keine 70 Bit darstellen, und die FileStreams in .NET liefern alle maximal 64-Bit-Längen bzw. -Positionen ;) |
War ja auch erstmal rein hypothetisch ;-) Wollt's auch nur erwähnt haben :mrgreen:
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!