18. marts 2006 - 02:18Der er
8 kommentarer og 1 løsning
Optimering af filsøgning
Hej Eksperter
Jeg har en flaskehals i mit system og ville høre om i kunne hjælpe med en smule optimering. Jeg har siddet og hygget mig lidt med problemet, men trænger nu til noget prof hjælp til at komme videre(Se timestamp på spørgsmål Hehe)
Problemet er basically filsøgning: Ud fra en mappestruktur med subdirs i en ukendt dybde og givet et filnavn ønskes det at finde den komplette sti til filen med dette filnavn. Input er altså et startDir(Eks. c:\) og et filnavn(eks minfil.ext), der muligvis er placeret i mappestrukturen under startDir. Bemærk at der kan være sub-subdirs i en ukendt dybde.
Jeg har bikset noget rekursiv kode sammen, der breaker, når en match er fundet. Se nedenstående klasse.
---------------------------- using System.IO;
public class DirSearcher { private string startDir; private string searchString; private bool itemFound; private string resultPath;
// Start the search for fileName in startDir using // recursive method searchDir public string search(string fileName) { this.searchString = fileName; this.resultPath = "No match"; searchDir(startDir); return result; }
private void searchDir(string dir) { if (!itemFound) // Dont investigate further, a match has been found { try { foreach (string d in Directory.GetDirectories(dir)) { foreach (string f in Directory.GetFiles(d, searchString)) { itemFound = true; return f; } searchDir(d); } } catch (Exception e) {} } }
static void Main() { DirSearcher ds = new DirSearcher("C:\\"); string res = ds.search("dotnetfx.exe"); Console.WriteLine(res); Console.Read(); } }
Jeg har dog behov for at kalde search metoden 100-500 gange på en mappestruktur i ukendt dybde, der let kan indeholde 70000+ filer. Dette er i øjeblikket laaaaaangsomt. Så spørgsmålet til jer er.... Kan metoden optimeres?
Jeg har kigget lidt på brug af Indexing Service i windows, men kan ikke finde et eksempel der uddyber emnet. Er det måske vejen frem.
Det skal nævnes, at jeg allerede har et funktionelt alternativ, hvor der først genereres en xml fil med de ønskede metadata fra alle filer i mappestrukturen(nej jeg ville ikke bare søge efter filer), hvorefter filnavnet kan benyttes som nøgle til at tilgå den ønskede fils metadata. Dette kræver dog, at der på forhånd genereres en temmelig stor xml fil og dette tager også lang tid. Jeg/vi vil derfor gerne undersøge om xml genereringen kan spares væk ved at søge efter filerne direkte.
Ser frem til at høre jeres bud på optimeringer eller alternative fremgangsmåder.
Allan
\* A programmer is just a tool to convert coke and smokes into code */
I lang tid har samarbejdsbranchen fokuseret på at forbedre enhedsfunktioner – bedre kameraer, klarere lyd og smartere software. Men den virkelige forvandling handler ikke om funktioner.
den hurtigste løsning må være en enkelt scan som læser alle 70000+ filer ind i en Hashtable med simpelt filnavn som key og fuldt filnavn eller dir som value
så kan du lave opslag på et par milliontedele sekunder
det koster så lidt memory (i størrelsesordenen 25-50 MB)
Der er et par bugs i den kode jeg fik sat ind. Glemte at jeg af pædagogiske årsager ændrede result-variablen til at hedde resultPath. Det slog ikke igennem i hele koden.
Please forgive klokken er halv 3 om natten og det er ikke nemt at se koden i de små vinduer man skal skrive spørgsmålet i :-)
using System.IO;
public class DirSearcher { private string startDir; private string searchString; private bool itemFound; private string resultPath;
// Start the search for fileName in startDir using // recursive method searchDir public string search(string fileName) { this.searchString = fileName; this.resultPath = "No match"; searchDir(startDir); return resultPath; }
private void searchDir(string dir) { if (!itemFound) // Dont investigate further, a match has been found { try { foreach (string d in Directory.GetDirectories(dir)) { foreach (string f in Directory.GetFiles(d, searchString)) { itemFound = true; resultPath = f; } searchDir(d); } } catch (Exception e) {} } }
static void Main() { DirSearcher ds = new DirSearcher("C:\\"); string res = ds.search("dotnetfx.exe"); Console.WriteLine(res); Console.Read(); } }
Det vil kræve en køretid i samme størrelsesorden som den nuværende kode kræver for den første søgning, men derefter vil de næste 499 søgninger være tæt på gratis..
Er der nogle kommentarer til den rekursive søgningteknik. Kan det gøres hurtigere eller har jeg fundet vejen frem.
hehe.. Må man nu ikke engang stille spørgsmålet før du svarer.....
Jeg har haft lidt problemer med at bryde ud af det rekursive kald. Derfor er der indsat variablen itemFound i class scope. Hvis jeg returnerer en værdi fra searchDir, så vil den jo overskrive min resulatet string var i search(), når det rekursive kald fortsætter???
Min ingeniør uddannelse rækker ikke til at stoppe rekursiviteten uden at bruge itemFound variablen. Kan jeg breake på andre måder.
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.