Last active
September 8, 2022 11:11
-
-
Save ThoNohT/9d71d25180fc6d674a2d7025b22431e7 to your computer and use it in GitHub Desktop.
Tail recursion and async
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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