1
以下の2つのタイミングが劇的に異なる理由は何ですか?私は10にpreinitilizedの数を変更した場合、それは何も変わりません:私はRunSynchronouslyのコスト
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下のオブジェクトプールを使用
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
。 遅さは、画面上の「カストを取得」が(ゆっくり)蓄積したときに、オブジェクトプールにメッセージを受信する前に発生し
興味深い。 RunSynchronouslyを呼び出すと、現在のスレッドプールを再利用できるという印象を受けました。 – nicolas
F#asyncsがThreadPoolを使用しています。 .NET ThreadPoolが小規模に開始され、キューに入れられたアイテムアクティビティの異常値バーストでリソースを無駄にするのを避けるために、スレッドをどれくらい迅速に割り当てるかを調整します。 – Brian
ありがとう、私はアップデートを投稿するのを忘れてしまった。あなたは正しいと思っていましたが、今は大丈夫です。私のプロジェクトを始めたとき、私はこれを深く考えたことはなかったでしょうが、理にかなっています。タックス – nicolas