Skip to content

Instantly share code, notes, and snippets.

@ThoNohT
Last active September 8, 2022 11:11
Show Gist options
  • Save ThoNohT/9d71d25180fc6d674a2d7025b22431e7 to your computer and use it in GitHub Desktop.
Save ThoNohT/9d71d25180fc6d674a2d7025b22431e7 to your computer and use it in GitHub Desktop.
Tail recursion and async
open BenchmarkDotNet.Attributes
open BenchmarkDotNet.Running
/// This function is recursive, but not tail recursive.
let rec countHigh (nr: int64) = if nr = 0L then 0L else countHigh (nr - 1L) + 1L
// This function is tail recursive.
let rec countHighTailRec (nr: int64) acc = if nr = 0L then acc else countHighTailRec (nr - 1L) (acc + 1L)
// This function is recursive in async, but not tail recursive.
let rec countHighAsync (nr: int64) = async {
if nr = 0L then
return 0L
else
let! next = countHighAsync (nr - 1L)
return next + 1L
}
// This function is tail recursive in async.
let rec countHighAsyncTailRec (nr: int64) acc = async {
if nr = 0 then
return acc
else
return! countHighAsyncTailRec (nr - 1L) (acc + 1L)
}
[<MemoryDiagnoser(false)>]
type Benchmarks () =
[<Benchmark>]
member _.TailRec () = countHighTailRec 100000L 0L
[<Benchmark>]
member _.AsyncRec () = Async.RunSynchronously <| countHighAsync 100000L
[<Benchmark>]
member _.AsyncTailRec () = Async.RunSynchronously <| countHighAsyncTailRec 100000L 0L
(*
| Method | Mean | Error | StdDev | Allocated |
|------------- |-------------:|-----------:|-------------:|-----------:|
| TailRec | 25.90 us | 0.253 us | 0.211 us | - |
| AsyncRec | 28,945.92 us | 524.885 us | 1,072.202 us | 26457041 B |
| AsyncTailRec | 2,805.48 us | 55.273 us | 79.271 us | 10419443 B |
*)
[<EntryPoint>]
let main _ =
ignore <| BenchmarkRunner.Run<Benchmarks> ()
printfn "Tail recursion: %i" <| countHighTailRec 100000L 0L
printfn "Async regular recursion: %i" <| Async.RunSynchronously (countHighAsync 100000L)
printfn "Async tail recursion: %i" <| Async.RunSynchronously (countHighAsyncTailRec 100000L 0L)
printfn "Regular recursion: %i" <| countHigh 100000L // Stack overflow.
1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment