Einzelnen Beitrag anzeigen

Benutzerbild von Union
Union

Registriert seit: 18. Mär 2004
Ort: Luxembourg
3.423 Beiträge
 
Delphi 7 Enterprise
 
#30

AW: Viele Dateien performant einlesen

  Alt 29. Apr 2014, 20:31
Fragt sich was das für ein Cache ist? Wenn ich folgendes Fragment vorschalte, in dem ich die Daten komplett einlese, wird das Verarbeiten danach wesentlich schneller:
Delphi-Quellcode:
  for i := Low(AFiles) to High(AFiles) do
  begin
    Watch.Start;
    fs := TFileStream.Create(AFiles[i], fmExclusive);
    SetLength(Buffer, fs.Size);
    fs.ReadBuffer(Buffer[0], fs.Size);
    Watch.Stop;
    fs.Free;
  end;
Diese Funktion braucht für 5.000 frisch erzeugte Dateien zwischen 500-1500 ms.

Wenn ich dann die Daten nochmals in Stringlisten einlese, werden 605-615 ms verbraucht.

Starte ich das Einlesen in die Stringlisten ohne den Vorlauf, braucht das beim ersten Mal 12000-13000 ms.

Vorlauf1500
Verarbeitung615
Summe2115
Direkte Verarbeitung13000

D.h. dieses Verfahren ist 6x schneller!

Komplettes Testprogramm:
Delphi-Quellcode:
unit main;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, System.Diagnostics;

type
  TForm1 = class(TForm)
    btnCreateData: TButton;
    btnRead: TButton;
    MemoProt: TMemo;
    btnOpen: TButton;
    procedure btnCreateDataClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure btnReadClick(Sender: TObject);
    procedure btnOpenClick(Sender: TObject);
  private
    { Private-Deklarationen }
    FDir : string;
    FWatch : TStopWatch;
    procedure Prot(const AMessage : string; AWatch : TStopWatch);
  public
    { Public-Deklarationen }
    property Watch : TStopWatch read FWatch;
  end;

var
  Form1: TForm1;

implementation

uses
  System.Types,
  System.IOUtils,
  System.StrUtils;

{$R *.dfm}

procedure TForm1.btnCreateDataClick(Sender: TObject);
var
  i : integer;
  Line : string;
begin
  Watch.Start;
  Line := Dupestring('ABCDEFGHI;', 2400);
  for i := 1 to 5000 do
    TFile.WriteAllText(TPath.Combine(FDir, Format('%4.4d.txt', [i])), Line);
  Watch.Stop;
  Prot('CreateFiles', Watch);
  Watch.Reset;
end;

procedure TForm1.btnOpenClick(Sender: TObject);
var
  AFiles : TStringDynArray;
  fs : TFileStream;
  i : integer;
  Buffer : TByteDynArray;
begin
  Watch.Start;
  AFiles := TDirectory.GetFiles(FDir);
  Watch.Stop;
  Prot('GetFiles', Watch);
  Watch.Reset;
  for i := Low(AFiles) to High(AFiles) do
  begin
    Watch.Start;
    fs := TFileStream.Create(AFiles[i], fmExclusive);
    SetLength(Buffer, fs.Size);
    fs.ReadBuffer(Buffer[0], fs.Size);
    Watch.Stop;
    fs.Free;
  end;
  Prot('Open', Watch);
  Watch.Reset;
end;

procedure TForm1.btnReadClick(Sender: TObject);
var
  AFiles : TStringDynArray;
  i : integer;
  Line : string;
  sl : TStringList;
  SplitWatch : TStopWatch;
begin
  Watch.Start;
  AFiles := TDirectory.GetFiles(FDir);
  Watch.Stop;
  Prot('GetFiles', Watch);
  Watch.Reset;

  sl := TStringList.Create;
  sl.Delimiter := ';';
  try
    SplitWatch := TStopWatch.Create;
    for i := Low(AFiles) to High(AFiles) do
    begin
      Watch.Start;
      Line := TFile.ReadAllText(AFiles[i]);
      Watch.Stop;
      SplitWatch.Start;
      sl.DelimitedText := Line;
      SplitWatch.Stop;
    end;
    Prot('ReadFiles', Watch);
    Prot('Split', SplitWatch);
  finally
    SplitWatch.Reset;
    Watch.Reset;
    sl.Free;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FDir := TPath.Combine(TPath.GetDirectoryName(Application.ExeName), 'Data');
  TDirectory.CreateDirectory(FDir);
  FWatch := TStopWatch.Create;
end;

procedure TForm1.Prot(const AMessage : string; AWatch : TStopWatch);
begin
  MemoProt.Lines.Add(AMessage + ' ' +AWatch.ElapsedTicks.ToString+' ticks, '+AWatch.ElapsedMilliseconds.ToString+' ms');
end;
Ibi fas ubi proxima merces
sudo /Developer/Library/uninstall-devtools --mode=all

Geändert von Union (29. Apr 2014 um 20:34 Uhr)
  Mit Zitat antworten Zitat