2009-11-23 16 views
5

Wir haben ein unerwartetes Leistungsproblem beim Durchlaufen von Verzeichnissen auf der Suche nach Dateien mit einem Platzhaltermuster aufgetreten.Win32 API FindFirstFile und FindNextFile Leistung vs Befehlszeile

Wir haben 180 Ordner mit jeweils 10.000 Dateien. Eine Befehlszeilensuche mit dir <pattern> /s wird fast sofort abgeschlossen (< 0,25 Sekunden). Allerdings dauert die Suche in unserer Anwendung zwischen 3 und 4 Sekunden.

Wir versuchten zunächst System.IO.DirectoryInfo.GetFiles() mit SearchOption.AllDirectories mit und haben versucht nun die Win32-API FindFirstFile() und FindNextFile() aufruft.

Profiling unserer Code mit zeigt an, dass die überwiegende Mehrheit der Ausführungszeit für diese Anrufe ausgegeben wird.

Unser Code ist auf der folgenden Blog-Post basiert:

http://codebetter.com/blogs/matthew.podwysocki/archive/2008/10/16/functional-net-fighting-friction-in-the-bcl-with-directory-getfiles.aspx

Wir fanden diese aktualisiert, so langsam zu sein, um die GetFiles Funktion ein string Suchmuster eher als ein Prädikat zu nehmen.

Kann jemand Licht in die Frage bringen, was mit unserem Ansatz falsch sein könnte?

+0

Was verwenden Sie für die Suche über die Befehlszeile? Könnte es sein, dass es die Windows-Suchindizes verwendet, um die Abfrage durchzuführen, anstatt jede Datei durchzugehen? –

+0

@Matt Wir machen nur ein 'dir/s' (habe meinen Beitrag entsprechend aktualisiert). –

+1

Klingt verdächtig. Ich bin mir ernsthaft sicher, dass "dir" alles andere als FindFirstFile/FindNextFile verwendet. Vielleicht missbrauchst du sie. Könnten Sie einen Ausschnitt bereitstellen, der veranschaulicht, wie Sie sie verwenden? – sharptooth

Antwort

2

Sie können mit einer Implementierung von FindFirstFile und FindNextFile I einmal blogged über versuchen.

+0

Unser Ansatz ist dem Darin sehr ähnlich –

+0

Ich habe meine Lösung getestet und es dauert 230 Millisekunden Zählen Sie ein Verzeichnis auf, das> 100K Dateien enthält. –

+0

Eine weitere Beschleunigung kann mit 'FindFirstFileEx (... FindExInfoBasic ...) erreicht werden.' – MSalters

0

Versuchen Sie IShellFolder::EnumObjects mit SHGetDataFromIDList/IShellFolder::GetAttributesOf.

Pro/Kons here.

7

In meinen Tests FindFirstFileEx mit FindExInfoBasic und FIND_FIRST_EX_LARGE_FETCH mit viel schneller ist als die Ebene Findfirstfile.

Das Scannen von 20 Ordnern mit ~ 300.000 Dateien dauerte 661 Sekunden mit FindFirstFile und 11 Sekunden mit FindFirstFileEx. Nachfolgende Aufrufe an die gleichen Ordner dauerte weniger als eine Sekunde.

HANDLE h = FindFirstFileEx (search.c_str(), FindExInfoBasic, & Daten, FindExSearchNameMatch, NULL, FIND_FIRST_EX_LARGE_FETCH);