AGB  ·  Datenschutz  ·  Impressum  







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

Schnelles Suchen nach Dateien

Ein Thema von GFEMajor · begonnen am 25. Jan 2009 · letzter Beitrag vom 25. Jan 2009
Antwort Antwort
GFEMajor

Registriert seit: 30. Dez 2008
15 Beiträge
 
#1

Schnelles Suchen nach Dateien

  Alt 25. Jan 2009, 09:29
Liebe Delphi Experten.
Ich habe wieder ein (für mich) großes Problem.

Ich arbeite immer noch an meiner Musiksuche, mit der ich Titel auf der Festplatte suchen kann.
Ich hab das ganze schonmal in Java umgesetzt und es so gemacht:
Alle Dateinamen in den Hauptspeicher lesen und dann dort suchen.

Jetzt wollte ich es in Delphi genauso machen, aber es geht einfach nicht schnell genug.
Ich suche mit FindFirst/FindNext usw alle Dateien in einem Wurzelverzeichnis und speichere die Dateinamen und den Pfad in einem Array vom Typ FileEntry (definition unten).
Es funktioniert zwar, aber viel zu langesam. Ich hab ca. 100.000 Dateien die hinzugefügt werden müssen.
Die Länge des Arrays setz ich schon ganz am Anfang, um es nicht jedes mal machen zu müssen, wenn ein Element hinzugefügt wird.

Hier mal die betreffenden Code Zeilen:

Delphi-Quellcode:
RFileEntry = packed record
 FileName: string[255];
 FilePath: string;
end;

procedure FindAllFiles(var FileEntrys : array of RCRSFileEntry; RootFolder: string; Mask: TStrings = nil; Recurse: Boolean = True);
var
  SR: TSearchRec;
  i: Integer;
  Item: RFileEntry;
begin
  RootFolder := IncludeTrailingPathDelimiter(RootFolder);
  if Mask = nil then
  begin
    Mask := TStringList.Create;
    Mask.Add('*.*');
  end;
  if Recurse then
    if FindFirst(RootFolder + '*.*', faAnyFile, SR) = 0 then
    try
      repeat
        if SR.Attr and faDirectory = faDirectory then // Verzeichnis
        begin
          if (SR.Name <> '.') and (SR.Name <> '..') then
          begin
            FindAllFiles(FileEntrys, RootFolder + SR.Name, Mask, Recurse);
          end;
        end else // Datei gefunden
        begin
          for i:= 0 to Mask.Count-1 do // schauen ob sie in der Maske ist
          begin
            if ExtractFileExt(SR.Name) = ExtractFileExt(Mask[i]) then
            begin
              Item.FileName := SR.Name;
              Item.FilePath := RootFolder;
              AddFileToFileList(Item);
            end;
          end;
        end;
      until FindNext(SR) <> 0;
    finally
      FindClose(SR);
    end;
end;

procedure AddFileToFileList(Item : RFileEntry);
begin
  Files[aktLength] := Item;
  Inc(aktLength);
end;
Files ist dabei eine Propery der Komponente, die das einlesen übernimmt.

Grund warum ich alles in den Speicher lade ist die Performance beim Suchen. Die eigentlich Suche soll richtig schnell gehen, da bei mir schon bei der Eingabe des Suchwortes (wenn 3-4 buchstaben eingegeben wurden) automatisch gesucht werden soll. Darum ist mit die Performance beim Suchen sehr wichtig.

Falls es eine (schnelle) Möglichkeit gibt direkt auf den Dateinamen zu suchen wäre ich auch zufrieden.
Vielleicht fällt ja jemand etwas ein, wie ich die ganze Sache beschleunigen kann. Zur Zeit braucht das einlesen ca. 30 min-1 Stunde (hab noch nicht genau gemessen). Das ist aber auf jeden Fall viel zu lange. Zeiten bis 5 Minuten (für das einladen) wären für mich noch akzeptabel.

LG und schonmal vielen Dank
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.851 Beiträge
 
Delphi 11 Alexandria
 
#2

Re: Schnelles Suchen nach Dateien

  Alt 25. Jan 2009, 09:31
Nimm keinen Array, sondern eine verkettete Liste
Markus Kinzler
  Mit Zitat antworten Zitat
GFEMajor

Registriert seit: 30. Dez 2008
15 Beiträge
 
#3

Re: Schnelles Suchen nach Dateien

  Alt 25. Jan 2009, 09:48
Ok, ich werd es mal Testen, aber warum sollte eine verkettete Liste schneller sein?
Ich leg ja das Array schon vor dem Einladen an. Es existieren also schon alle Einträge (nur ohne die richtigen Werte ). Und zur Laufzeit weise ich dann die Werte zu.

Bei einer List müsste ich in jedem Durchlauf ein Element anlegen und Zeiger setzen.

Edit:
----

Ich hab jetzt mal noch ne kleinere Zeitmessung gemacht. uUnd zwar mit folgendem Code:

Delphi-Quellcode:
procedure TCRSDataSourceFile.FindAllFiles(var FileEntrys : array of RCRSFileEntry; RootFolder: string; Mask: TStrings = nil; Recurse: Boolean = True);
var
  SR: TSearchRec;
  i: Integer;
  Item: RCRSFileEntry;
begin
  RootFolder := IncludeTrailingPathDelimiter(RootFolder);
  if Mask = nil then
  begin
    Mask := TStringList.Create;
    Mask.Add('*.*');
  end;
  if Recurse then
    if FindFirst(RootFolder + '*.*', faAnyFile, SR) = 0 then
    try
      repeat
        if SR.Attr and faDirectory = faDirectory then // Verzeichnis
        begin
          if (SR.Name <> '.') and (SR.Name <> '..') then
          begin
            FindAllFiles(FileEntrys, RootFolder + SR.Name, Mask, Recurse);
          end;
        end else // Datei gefunden
        begin
          aktLength := 0;
        end;
      until FindNext(SR) <> 0;
    finally
      FindClose(SR);
    end;
end;
Es wird also nichts mit den Dateien gemacht. Nur jede einmal angefasst. Und da dauert das einlesen von 10.000 Elementen schon 3 Minute lang. Ich denke also, der Beschränkende Faktor ist entweder die Festplattengeschwindigkeit oder Die Funkntionen FindFist/FindNext usw.
Oder habt ihr eine andere Idee?
  Mit Zitat antworten Zitat
Hawkeye219

Registriert seit: 18. Feb 2006
Ort: Stolberg
2.227 Beiträge
 
Delphi 2010 Professional
 
#4

Re: Schnelles Suchen nach Dateien

  Alt 25. Jan 2009, 10:48
Hallo,

einige Dinge sind mir aufgefallen:

1. Du verwendest für den Dateinamen einen ShortString - warum? Beim Übertragen in den Record müssen so immer 256 Bytes bewegt werden, während bei der Verwendung dynamischer Strings wahrscheinlich nur ein Referenzzähler erhöht werden muss.

2. Bei jedem Vergleich der Extensions rufst du die Funktion ExtractFileExt auf, obwohl sich die Extensions in der Liste während der Suche nicht ändern. Vielleicht wäre es günstiger, für die Liste die Sortierung einzuschalten und mittels TStringList.IndexOf zu suchen. Damit hättest du gleichzeitig das Problem der Groß-/Kleinschreibung erschlagen.
Falls du an deiner Suchschleife festhalten möchtest, solltest du sie übrigens nach einem Fund abbrechen. Warum weiter suchen, wenn die Datei schon als "bekannt" identifiziert wurde?

3. Wenn die Routine ohne Maske aufgerufen wird, erzeugt sie intern eine Stringliste. Dieses Objekt wird aber nie freigegeben.

Diese Hinweise werden sicher nicht alle Performanceprobleme lösen, aber vielleicht sind dennoch nützlich. An FindFirst/FindNext wirst du kaum vorbeikommen.

Ich habe deinen letzten Code übrigens einmal (unverändert) auf meine externe Festplatte losgelassen. Nach 145 Sekunden hattte er knapp 100.000 Dateien gefunden (Core2Duo, 2.4 GHz).

Gruß Hawkeye
  Mit Zitat antworten Zitat
GFEMajor

Registriert seit: 30. Dez 2008
15 Beiträge
 
#5

Re: Schnelles Suchen nach Dateien

  Alt 25. Jan 2009, 11:02
Ich hab auch das Problem gefunden, warum es so lange dauert. Ich hatte die Optimierung im Compiler ausgeschaltet (mach ich oft im Entwicklungsmodus, damit nicht irgendwelche wichtigen variablen zur Debugzeit "wegoptimiert" werden).
Optimierung an und das einladen geht in wenigen Sekunden .
Die Anregungen werd ich mir zu Herze nehmen und die Sachen noch anpassen .

Vielen dank auf jeden fall.
  Mit Zitat antworten Zitat
Benutzerbild von Meflin
Meflin

Registriert seit: 21. Aug 2003
4.856 Beiträge
 
#6

Re: Schnelles Suchen nach Dateien

  Alt 25. Jan 2009, 11:06
Zitat von GFEMajor:
Ich hatte die Optimierung im Compiler ausgeschaltet (mach ich oft im Entwicklungsmodus, damit nicht irgendwelche wichtigen variablen zur Debugzeit "wegoptimiert" werden
Wenn sie wirklich wichtig sind, dann können sie eigentlich nicht wegoptimiert werden
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.171 Beiträge
 
Delphi 10.4 Sydney
 
#7

Re: Schnelles Suchen nach Dateien

  Alt 25. Jan 2009, 11:07
Ein kleines Const bring auch etwas bei funktionsparameter deren SizeOf > 4 Byte ist:

procedure AddFileToFileList(const Item : RFileEntry);
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
GFEMajor

Registriert seit: 30. Dez 2008
15 Beiträge
 
#8

Re: Schnelles Suchen nach Dateien

  Alt 25. Jan 2009, 12:01
Zitat von Meflin:
Zitat von GFEMajor:
Ich hatte die Optimierung im Compiler ausgeschaltet (mach ich oft im Entwicklungsmodus, damit nicht irgendwelche wichtigen variablen zur Debugzeit "wegoptimiert" werden
Wenn sie wirklich wichtig sind, dann können sie eigentlich nicht wegoptimiert werden
Nicht unbedingt wichtig für die Ausführung, aber manchmal wichtig für das Verständnis um Fehler zu finden .
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.851 Beiträge
 
Delphi 11 Alexandria
 
#9

Re: Schnelles Suchen nach Dateien

  Alt 25. Jan 2009, 12:04
So werden z.B. oft beim Debuggen, für das Verständis, die Fehlersuche wichtige Variablen wegoptimiert
Markus Kinzler
  Mit Zitat antworten Zitat
Benutzerbild von thkerkmann
thkerkmann

Registriert seit: 7. Jan 2006
Ort: Pulheim Brauweiler
464 Beiträge
 
Delphi 2010 Professional
 
#10

Re: Schnelles Suchen nach Dateien

  Alt 25. Jan 2009, 12:56
Zitat von mkinzler:
So werden z.B. oft beim Debuggen, für das Verständis, die Fehlersuche wichtige Variablen wegoptimiert
Äh, hast Du an diesem Satz irgendwas wegoptimiert ?
Thomas Kerkmann
Ich hab noch einen Koffer in Borland.
http://thomaskerkmann.wordpress.com/
  Mit Zitat antworten Zitat
Antwort Antwort


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 19:43 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