|
let select connection query =
|
|
async {
|
|
do! Async.Sleep(1000)
|
|
ignore <| printfn "Selecting %s on %s" query connection
|
|
return [1; 2; 3]
|
|
}
|
|
|
|
let execute connection query =
|
|
async {
|
|
do! Async.Sleep(1000)
|
|
ignore <| printfn "Executing %s on %s" query connection
|
|
return true
|
|
}
|
|
|
|
let statistics name op =
|
|
let stopwatch = System.Diagnostics.Stopwatch.StartNew()
|
|
let result = op()
|
|
stopwatch.Stop()
|
|
ignore <| printfn "Measured %s at %.3f seconds" name (float stopwatch.ElapsedMilliseconds / 1000.0)
|
|
result
|
|
|
|
let statisticsAsync name op =
|
|
async {
|
|
let stopwatch = System.Diagnostics.Stopwatch.StartNew()
|
|
let! result = op
|
|
stopwatch.Stop()
|
|
ignore <| printfn "Measured %s at %.3f seconds" name (float stopwatch.ElapsedMilliseconds / 1000.0)
|
|
return result
|
|
}
|
|
|
|
let memoize (cache:Map<'a,'b> ref) key f =
|
|
match cache.Value.TryFind key with
|
|
| Some(result) -> result
|
|
| None ->
|
|
printfn "Instantiating Query Object"
|
|
let result = f()
|
|
cache.Value <- cache.Value.Add(key, result)
|
|
result
|
|
|
|
let memoizeAsync (cache:Map<'a,'b> ref) key f =
|
|
match cache.Value.TryFind key with
|
|
| Some(result) -> async { return result }
|
|
| None ->
|
|
printfn "Instantiating Query Object"
|
|
async {
|
|
let! result = f()
|
|
cache.Value <- cache.Value.Add(key, result)
|
|
return result
|
|
}
|
|
|
|
let runWithTimeout timeout op =
|
|
try
|
|
let result = Async.RunSynchronously(op, timeout)
|
|
printfn "Did not timeout! Yay fast database!"
|
|
Some(result)
|
|
with
|
|
| :? System.TimeoutException -> printfn "Timed out after %d milliseconds" timeout; None
|
|
|
|
type IEvaluator =
|
|
abstract member Select : string -> int list option
|
|
abstract member Execute : string -> bool option
|
|
abstract member Name : string
|
|
|
|
let createEvaluator connection =
|
|
let cache = ref Map.empty
|
|
{ new IEvaluator with
|
|
member x.Select(query) = (fun () -> select connection query)
|
|
|> memoizeAsync cache query
|
|
|> statisticsAsync "select"
|
|
|> runWithTimeout 2000
|
|
member x.Execute(query) = execute connection query
|
|
|> statisticsAsync "execute"
|
|
|> runWithTimeout 2000
|
|
member x.Name = "Forward" }
|
|
|
|
let createReversedEvaluator connection =
|
|
let cache = ref Map.empty
|
|
{ new IEvaluator with
|
|
member x.Select(query) = (fun () ->
|
|
(fun () ->
|
|
select connection query
|
|
|> runWithTimeout 2000)
|
|
|> statistics "select")
|
|
|> memoize cache query
|
|
member x.Execute(query) = (fun () -> execute connection query
|
|
|> runWithTimeout 2000)
|
|
|> statistics "execute"
|
|
member x.Name = "Backward" }
|
|
|
|
let evaluators = List.map (fun evaluator -> evaluator "Connection String") [createEvaluator; createReversedEvaluator]
|
|
|
|
for evaluator in evaluators do
|
|
printfn "%s:" evaluator.Name
|
|
printfn "Result: %O" <| evaluator.Select "SELECT ... FROM ... FOR UPDATE ..."
|
|
printfn "Result: %O" <| evaluator.Select "SELECT ... FROM ... FOR UPDATE ..."
|
|
printfn "Result: %O" <| evaluator.Execute "INSERT ..."
|
|
printfn ""
|