Cost of RunSynchronously

ⅰ亾dé卋堺 提交于 2019-12-24 10:44:38

问题


What are the reasons why the two timings below differs so dramatically ?

     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

I use the object pool below

   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 : if I change the number of preinitilized to 10, it does not change anything. The slowness occurs before receiving the message in the object pool, when it accumulates (slowly) 'acquiring cust' on the screen


回答1:


Try putting it in a loop:

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

I think you are just witnessing the initial time to warm up the threadpool (which only likes two add two threads per second by default); once it is warm, things are fast.



来源:https://stackoverflow.com/questions/9955960/cost-of-runsynchronously

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!