2012-03-31 3 views
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 

。 遅さは、画面上の「カストを取得」が(ゆっくり)蓄積したときに、オブジェクトプールにメッセージを受信する前に発生し

答えて

2

ループでそれを入れてみてください:

for i in 1..5 do 
    time acquire // 76 ms 
    time acquire2 // 5310 ms 

を私はあなただけで目撃されていると思いますスレッドプールをウォーミングアップする最初の時間(デフォルトでは、2つのスレッドのみが2つのスレッドを追加します)。一度それが暖かい、物事は速いです。

+0

興味深い。 RunSynchronouslyを呼び出すと、現在のスレッドプールを再利用できるという印象を受けました。 – nicolas

+0

F#asyncsがThreadPoolを使用しています。 .NET ThreadPoolが小規模に開始され、キューに入れられたアイテムアクティビティの異常値バーストでリソースを無駄にするのを避けるために、スレッドをどれくらい迅速に割り当てるかを調整します。 – Brian

+1

ありがとう、私はアップデートを投稿するのを忘れてしまった。あなたは正しいと思っていましたが、今は大丈夫です。私のプロジェクトを始めたとき、私はこれを深く考えたことはなかったでしょうが、理にかなっています。タックス – nicolas

関連する問題