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
Try putting it in a loop:
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.