![]() |
Re: Format-Funktion zu langsam
Array-Properties koenne erschreckend langsam sein.
Ich habe ein Programm 10x schneller bekommen indem ich die booleschen Werte nicht dauernd aus der Checked-Property eines Listviews gelesen habe. Einmal in ein array von Booleans kopiert und alles war gut eh schnell. |
Re: Format-Funktion zu langsam
Ich habe es eben mal aus Jux (und aufgrund der Mittagspause :zwinker: ) in .Ne probiert.
Fazit: Es ist langsamer, aber es ist auch alles andere als hübsch oder optimiert. :P Ich komme auf create array: 0.3967 ms fill 8,000,000 random values: 427.5188 ms conversion: 8054.1218 ms write to disk: 13924.7499 ms overall time: 22457.428 ms Press any key to continue
Code:
using System;
using System.Collections; using System.IO; using RobertG.Invoked.ProcessInfo; namespace DelphiPRAXIS.Jelly.Save3dArray { internal class Program { /// <summary> /// Entry point /// </summary> /// <param name="args">Argumente (Nummer eins ist das zu schreibende Dateichen)</param> [STAThread] static void Main(string[] args) { Program program = new Program(); program.Run(args[0]); } PerformanceCounter counter; double[,,] values; public Program() { counter = new PerformanceCounter(); } void Run(string fileName) { PerformanceCounter overallCounter = new PerformanceCounter(); overallCounter.Start(); values = CreateArray(); int valueCount = (int)values.LongLength; FillRandomNumbers(valueCount); ArrayList lines = new ArrayList(valueCount); ConvertNumbers(lines); SaveToFile(fileName, lines); overallCounter.Stop(); Console.WriteLine("overall time: {0:0.####} ms", overallCounter.Duration); } double[,,] CreateArray() { counter.Start(); double[,,] values = Array.CreateInstance(typeof (double), new int[3] {200, 200, 200}) as double[,,]; counter.Stop(); Console.WriteLine("create array: {0:0.####} ms", counter.Duration); return values; } void FillRandomNumbers( int valueCount) { counter.Start(); Random random = new Random(valueCount); for (int i = 0; i < values.GetLength(0); i++) { for (int j = 0; j < values.GetLength(1); j++) { for (int k = 0; k < values.GetLength(2); k++) { values[i, j, k] = random.NextDouble(); } } } counter.Stop(); Console.WriteLine("fill {0:0,0} random values: {1:0.####} ms", values.LongLength, counter.Duration); } void ConvertNumbers(ArrayList lines) { counter.Start(); foreach (double value in values) { lines.Add(value.ToString("0.####")); } counter.Stop(); Console.WriteLine("conversion: {0:0.####} ms", counter.Duration); } void SaveToFile(string fileName, IList lines) { FileStream stream = null; counter.Start(); if (File.Exists(fileName)) { stream = new FileStream(fileName, FileMode.Truncate, FileAccess.Write); } else { stream = new FileStream(fileName, FileMode.CreateNew, FileAccess.Write); } BinaryWriter writer = new BinaryWriter(stream); foreach (string line in lines) { writer.Write(line); } stream.Close(); counter.Stop(); Console.WriteLine("write to disk: {0:0.####} ms", counter.Duration); } } } |
Re: Format-Funktion zu langsam
Ich glaube in meinem Fall hängt es wirklich an der Format oder FormatFloat Funktion... Das Schreiben der Daten klappt recht schnell. Sobald irgendwo ein Aufruf mit Format o.ä. drin steht, dauerts Minuten...
|
Re: Format-Funktion zu langsam
Delphi-Quellcode:
das ist ineffizient und unleserlich.
procedure TMCBasisExport.Add(AText: string);
var buf : string ; begin if FS <> nil then begin buf := AText+#13#10 ; FS.Write(buf[1],length(buf)) ; end else begin raise exception.Create('Datei kann nich beschrieben werden.'); end ; end;
Delphi-Quellcode:
Die Contentation in deinem Source mit Buf := AText + #13#10 führt minimal vier langwierige und unnötige Operationen aus, die du so nicht siehst:
procedure TMCBasisExport.Add(const AText: String);
const CR: PChar = #13#10; begin if FS = nil then raise exception.Create('Kein Dateistream erzeugt.'); FS.Write(PChar(AText)^, Length(AText)); FS.Write(CR^, 2); end; 1.) Buf = AText -> setze @Buf^ = @AText^, interner AText.RefCounter +1 erhöhen 2.) Buf = Buf + #13#10 2.1.) alloziere neuen Speicher mit Length(AText) + 4 2.2.) kopiere Inhalt von AText == Buf nach neuen Speicher 2.3.) AText.RefCounter -1 2.4.) setze Buf auf neuen Speicher 2.5.) falls (Length(ABuf) + 4) mod 16 < 2 dann 2.5.1.) alloziere neuen Speicher mit Length(Buf) + 2 um #13#10 hinzufügen zu können 2.5.2.) kopiere nun Buf nach neuen Speicher 2.5.3.) dealloziere alten Speicher im Buf 2.5.4.) setze Buf auf neuen Speicher 2.6.) setze Länge vom String Buf auf ++2 2.7.) kopiere #13#10 ans Ende von Buf 2.8.) Buf.RefCounter -1 2.9.) Speicher in Buf freigeben All das passiert bei Buf := AText + #13#10; In meinem Beispiel passiert dagegen folgendes: 0.) nichts, kein unnötiges Stringhandling Gruß Hagen |
Re: Format-Funktion zu langsam
@Hagen:
dein Code mag ja effetkiver sein, da stimm ich dir zu. Werd das mal umbauen... Nur wird meine funktion dadurch nicht viel schneller, da alle Zeit in der Format-Funktion verbraten wird... Aber da schein ich nix dran ändern zu können. Muss ich halt warten. |
Re: Format-Funktion zu langsam
hast du es denn schon umgebaut und getestet ?
Gruß Hagen |
Re: Format-Funktion zu langsam
Zitat:
Man lernt halt nie aus. |
Re: Format-Funktion zu langsam
Gut, du hast also gelernt das die Contenation von LongStrings sehr langsam sind und das es eventuell besser sein kann erstmal einfach die Tipps der erfahrenen Programmierer nicht sofort anzuzweifeln :)
In deinem Source betrifft das 6 Stellen:
Delphi-Quellcode:
Statt also mit V_line[nr] zu arbeiten änderst du sie in Aufrufe von Add() um. Im .Add() nimmst du das #13#10 raus und baust es manuell in deine Schleife rein.
V_line[Nr] := format('%s (:,:,%d) = [',[A[Nr],iz+1]) ;
V_line[Nr] := V_line[Nr] + FloatToStrF (C[Nr],ffFixed,7,4) + ' ' ; // langsam, heisst ung. 20 min. //V_line[Nr] := V_line[Nr] + '0.0001 ' ; // schnell, par Sekündchen if (iy = G.y-1) and (ix < G.x-1) then begin V_line[Nr] := V_line[Nr] + '; ' ; end ; end ; end ; V_line[Nr] := V_line[Nr] + '] ;' ; .Add() selber kann nun zusätzlich beschleunigt werden indem man einen zb. 4Kb großen Buffer benutzt. Das beschleunigt dann das Dateisystem des Betriebsystemes das mit 1Kb-4Kb großen Schreibzugriffen am effizientesten ist. Als nächstes würde man die Format() und FloatToStrF() funktionen umbauen. Diese würde dann NICHT mehr einen LongString als Resultat zurückgeben sondern in diesem großen Buffer[] direkt hinein-formatieren. Somit wären alle LongString's und deren ständige Speicher- Alloziereungen/Deallozioerungen/Kopierungen entfernt. Deine Funktion könnte abstrahiert dann so aussensehen:
Delphi-Quellcode:
Der Buffer wird überdimensioniert um Overhang Zeichen damit nun die neuen Funktionen für Format(), FloatToStrF() in den Buffer direkt formatieren können.
procedure ExportMatrix(const Filename: String, ... blabla);
const Overhang = 256; var Buffer: array[0..1024 * 4 -1 + Overhang] of Char; // 256 zeichen mehr für inplaced Format() etc. funktionen BufPos: Integer; Stream: TStream; procedure WriteBuffer; begin Stream.Write(Buffer, BufPos); BufPos := 0; end; procedure Put(Text: Char); overload; begin Buffer[BufPos] := Text; Inc(BufPos); if BufPos >= SizeOf(Buffer) - Overhang then WriteBuffer; end; procedure Put(const Text: PChar); overload; begin with Text^ <> #0 do begin Put(Text^); Inc(Text); end; end; procedure DoExport; var I,J: Integer; ..,blabla begin // hier Matrix exportieren for I := 0 to do for J := 0 to do begin Put(...); for K := 0 to do begin Put(...); Put(' '); end; Put(#13#10); end; end; begin BufPos := 0; Stream := TFileStream.Create(FileName, fmCreate); try DoExport; WriteBuffer; // Rest des Buffers speichern finally Stream.Free; end; end; Gruß Hagen |
Re: Format-Funktion zu langsam
Zu meiner Schande muß ich gestehen, daß ich noch nie so tief Zeit in die Performance von Algos reingesteckt habe. :oops:
Ich nehm mir deinen Rat zu Herzen und werds einbauen, rsp mich zumindest mehr mit so Problemen allg. beschäftigen. Aber unter Zeitdruck klappt das nun mal leider nicht immer ;-) Danke für den Tip... :zwinker: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:37 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz