"Say unto thine own heart, I am mine own redeemer"
Don't touch me when I'm crazy of that airplane glue
Läsa kataloger parallellt med F#
Visa signatur
Tjo
Det är så att jag försöker lära mig lite F# och har ännu inte fått den där aha-upplevelsen som man vill ha när man lär sig nåt nytt. Det jag försöker göra är att gå igenom ett filträd rekursivt och plocka ut sökvägen till alla .exe-filer. Rekursionen är tänkt att fungera så att för varje undermapp skapar man en ny parallell exekvering och kan på så sätt snabba upp det hela lite. Dock har jag nånstans problem med enhetestyper vilket gör att mitt lilla program inte fungerar, men kan inte lista ut vad som är felet, så all hjälp uppskattas.
let rec GetDirrs root =
Seq.append
(root |> Directory.GetFiles |> Array.filter(fun x -> x.ToLower().EndsWith(".exe")) |> Array.toSeq)
(Async.Parallel[for subdir in Directory.GetDirectories(root) -> async{ return GetDirrs subdir}] |> Async.RunSynchronously)
"Say unto thine own heart, I am mine own redeemer"
Don't touch me when I'm crazy of that airplane glue
nyfiken på om det verkligen går fortare, eftersom du måste läsa på massa olika ställen på hårddisken?
Om du slänger på
|> Seq.fold Seq.append Seq.empty
så att du får
let rec GetDirrs root =
Seq.append
(root |> Directory.GetFiles |> Array.filter(fun x -> x.ToLower().EndsWith(".exe")) |> Array.toSeq)
(Async.Parallel[for subdir in Directory.GetDirectories(root) -> async{ return GetDirrs subdir}] |> Async.RunSynchronously |> Seq.fold Seq.append Seq.empty)
så fungerar det.
Ett tips är att om du explicit skriver in typen på funktionen du skriver så kan det bli lättare att hitta felet, för då försöker inte kompilatorn att hitta på en ny typ som inte stämmer pga något annat fel i funktionen.
let rec GetDirs (root:string) : seq<string> = ...
Genom att använda funktionen collect så kan man skriva funktionen så här:
let rec GetDirs path =
Array.append
(path |> Directory.GetFiles |> Array.filter (fun x -> x.ToLower().EndsWith(".exe")))
(path |> Directory.GetDirectories |> Array.Parallel.collect GetDirs)
Då kan man lätt byta Array.Parallel.collect mot Array.collect ifall man vill köra sekventiellt istället.
Som gothxx misstänkte så går det i praktiken väldigt mycket långsammare att köra det här parallellt, antagligen för att trycket på filsystemet gör att det chokar.
Copyright © 1999–2023 Geeks AB. Allt innehåll tillhör Geeks AB.
Citering är tillåten om källan anges.