Aus welchen Gründen unterscheiden sich die beiden folgenden Timings so drastisch?Kosten von RunSynchronously
let time acquire =
let sw = System.Diagnostics.Stopwatch.StartNew()
sw.Start()
let tsks = [1 .. 10] |> Seq.map (fun x -> acquire)
let sec = Async.RunSynchronously(Async.Parallel tsks)
sw.Stop()
printfn "Generation time %A ms" sw.Elapsed.TotalMilliseconds
sw.Reset()
Console.ReadKey() |> ignore
let custPool = ObjectPool(customerGenerator, 0)
let acquire = async { printfn "acquiring cust" ; return! custPool.Get() }
let acquire2 = async { return Async.RunSynchronously(acquire)}
time acquire // 76 ms
time acquire2 // 5310 ms
ich das Objekt Pool nutzen unter
type ObjectPool<'a>(generate: unit -> 'a, initialPoolCount) =
let initial = List.init initialPoolCount (fun (x) -> generate())
let agent = Agent.Start(fun inbox ->
let rec loop(x) = async {
let! msg = inbox.Receive()
match msg with
| Get(reply) -> let res = match x with | a :: b -> reply.Reply(a);b
| [] as empty-> reply.Reply(generate());empty
printfn "gave one, %A left" (Seq.length res)
return! loop(res)
| Put(value) -> printfn "got back one, %A left" ((Seq.length x) + 1)
return! loop(value :: x)
| Clear(reply) -> reply.Reply x
return! loop(List.empty<'a>)
}
loop(initial))
/// Clears the object pool, returning all of the data that was in the pool.
member this.ToListAndClear() = agent.PostAndAsyncReply(Clear)
/// Puts an item into the pool
member this.Put (item) = agent.Post(item)
/// Gets an item from the pool or if there are none present use the generator
member this.Get (item) = agent.PostAndAsyncReply(Get)
type Customer = {First : string; Last : string; AccountNumber : int;} override m.ToString() = sprintf "%s %s, Acc: %d" m.First m.Last m.AccountNumber
let names,lastnames,rand = ["John"; "Paul"; "George"; "Ringo"], ["Lennon";"McCartney";"Harison";"Starr";],System.Random()
let randomFromList list= let length = List.length list
let skip = rand.Next(0, length)
list |> List.toSeq |> (Seq.skip skip) |> Seq.head
let customerGenerator() = { First = names |> randomFromList;
Last= lastnames |> randomFromList;
AccountNumber = rand.Next();}
NB: Wenn ich die Anzahl der preinitilized bis 10 zu ändern, es ändert nichts. Die Langsamkeit auftritt, bevor die Nachricht im Objektpool empfängt, wenn es sich ansammelt (langsam) ‚cust erwerben‘ auf dem Bildschirm
interessant. Als ich RunSynchronously anrief, hatte ich den Eindruck, dass es den aktuellen Threadpool einfach wiederverwenden könnte. – nicolas
Die F # asyncs verwenden den ThreadPool. Es ist nur so, dass der .NET ThreadPool klein anfängt und drosselt, wie schnell er mehr Threads zuweist, um zu vermeiden, dass Ressourcen bei einem Ausreißer von Warteschlangen-Items verschwendet werden. – Brian
Danke, dass ich vergessen habe, ein Update zu posten. Du hattest Recht, und ich habe einen SetMinThread hinzugefügt, jetzt ist es in Ordnung. Ich hätte nie gedacht, dass ich so tief gehe, aber es macht Sinn. Thks – nicolas