AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Format-Funktion zu langsam

Ein Thema von Jelly · begonnen am 25. Jan 2005 · letzter Beitrag vom 27. Jan 2005
Antwort Antwort
Seite 2 von 2     12   
Robert Marquardt
(Gast)

n/a Beiträge
 
#11

Re: Format-Funktion zu langsam

  Alt 26. Jan 2005, 13:10
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.
  Mit Zitat antworten Zitat
Robert_G
(Gast)

n/a Beiträge
 
#12

Re: Format-Funktion zu langsam

  Alt 26. Jan 2005, 13:43
Ich habe es eben mal aus Jux (und aufgrund der Mittagspause ) in .Ne probiert.
Fazit: Es ist langsamer, aber es ist auch alles andere als hübsch oder optimiert.

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);
        }
    }
}
  Mit Zitat antworten Zitat
Benutzerbild von Jelly
Jelly

Registriert seit: 11. Apr 2003
Ort: Moestroff (Luxemburg)
3.741 Beiträge
 
Delphi 2007 Professional
 
#13

Re: Format-Funktion zu langsam

  Alt 26. Jan 2005, 14:04
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...
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#14

Re: Format-Funktion zu langsam

  Alt 27. Jan 2005, 06:08
Delphi-Quellcode:
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;
das ist ineffizient und unleserlich.

Delphi-Quellcode:
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;
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:

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
  Mit Zitat antworten Zitat
Benutzerbild von Jelly
Jelly

Registriert seit: 11. Apr 2003
Ort: Moestroff (Luxemburg)
3.741 Beiträge
 
Delphi 2007 Professional
 
#15

Re: Format-Funktion zu langsam

  Alt 27. Jan 2005, 08:56
@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.
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#16

Re: Format-Funktion zu langsam

  Alt 27. Jan 2005, 15:08
hast du es denn schon umgebaut und getestet ?

Gruß Hagen
  Mit Zitat antworten Zitat
Benutzerbild von Jelly
Jelly

Registriert seit: 11. Apr 2003
Ort: Moestroff (Luxemburg)
3.741 Beiträge
 
Delphi 2007 Professional
 
#17

Re: Format-Funktion zu langsam

  Alt 27. Jan 2005, 16:27
Zitat von negaH:
hast du es denn schon umgebaut und getestet ?
Grad eben, und es läuft wesentlich schneller...

Man lernt halt nie aus.
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#18

Re: Format-Funktion zu langsam

  Alt 27. Jan 2005, 18:04
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:
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] + '] ;' ;
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.

.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:
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;
Der Buffer wird überdimensioniert um Overhang Zeichen damit nun die neuen Funktionen für Format(), FloatToStrF() in den Buffer direkt formatieren können.

Gruß Hagen
  Mit Zitat antworten Zitat
Benutzerbild von Jelly
Jelly

Registriert seit: 11. Apr 2003
Ort: Moestroff (Luxemburg)
3.741 Beiträge
 
Delphi 2007 Professional
 
#19

Re: Format-Funktion zu langsam

  Alt 27. Jan 2005, 20:39
Zu meiner Schande muß ich gestehen, daß ich noch nie so tief Zeit in die Performance von Algos reingesteckt habe.

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...
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:24 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz