Skip to content

Commit

Permalink
Benchmarks for Alternative Implementations, Inline, and InlineIfLambda (
Browse files Browse the repository at this point in the history
#166)

* benchmarks

* update gitignore

* Remove artifacts

* Adds InlineIfLambda variants

* Adds additional variations on benchmark

* revert Result.fs

* Adds bind CE and bind same benchmarks

* Adding Task and Async Result CE benchmarks

* First pass at InlineIfLambda with backwards compatability

* formatting async.fc

* Convert AsyncOption.fs to use InlineIfLambda

* get tests running for each netstandard

* Gets all tests working with correct TFM split

* Update FAKE to fix CI

* formatting

* update dotnet-fable

* AsyncOptionCE using inlineiflambda

* Update CI to install dotnet versions

* global json woes?

* formatting

* AsyncResult InlineIfLambda

* AsyncResultCE and Op InlineIfLambda

* AsyncResultOption InlineIfLambda

* Option InlineIfLambda

* formatting

* Result InlineIfLambda

* Validation InlineIfLambda

* ValueOption inlineiflambda

* AsyncSeq InlineIfLambda

* Speedily added InlineIfLambda to Taskresult

* speedily add InlineIfLambda to JobResult

* warning cleanups

* That fun CI wackahole part 1

* That fun CI wackahole

* That fun CI wackahole

* Move fake build to console app

* Paket targets

* no more need for double underscore in classes
  • Loading branch information
TheAngryByrd authored Feb 21, 2022
1 parent f5019f1 commit 69b0019
Show file tree
Hide file tree
Showing 86 changed files with 4,336 additions and 1,184 deletions.
8 changes: 1 addition & 7 deletions .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,14 @@
"version": 1,
"isRoot": true,
"tools": {
"fake-cli": {
"version": "5.20.4",
"commands": [
"fake"
]
},
"paket": {
"version": "6.2.1",
"commands": [
"paket"
]
},
"fable": {
"version": "3.4.9",
"version": "3.7.1",
"commands": [
"fable"
]
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ jobs:
uses: actions/setup-dotnet@v1
with:
dotnet-version: '3.1.x'
- name: Use .NET Core 5.x SDK
uses: actions/setup-dotnet@v1
with:
dotnet-version: '5.0.x'
# Not specifying a version will attempt to install via global.json
- name: Use .NET Core global.json
uses: actions/setup-dotnet@v1
Expand Down
8 changes: 5 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,6 @@ flycheck_*.el
x64/
x86/
bld/
build/
[Bb]in/
[Oo]bj/
[Ll]og/
Expand Down Expand Up @@ -382,7 +381,6 @@ FakesAssemblies/
_Pvt_Extensions

# Paket dependency manager
.paket
paket-files/

# FAKE - F# Make
Expand All @@ -399,4 +397,8 @@ paket-files/
fable_modules
.fable
*.fs.js
js-dist/
js-dist/


# Benchmarks
benchmarks/BenchmarkDotNet.Artifacts/
557 changes: 557 additions & 0 deletions .paket/Paket.Restore.targets

Large diffs are not rendered by default.

40 changes: 40 additions & 0 deletions FsToolkit.ErrorHandling.sln
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FsToolkit.ErrorHandling.Asy
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FsToolkit.ErrorHandling.AsyncSeq.Tests", "tests\FsToolkit.ErrorHandling.AsyncSeq.Tests\FsToolkit.ErrorHandling.AsyncSeq.Tests.fsproj", "{5DED3CA8-B331-4B48-A6A2-2EE1410437CA}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "benchmarks", "benchmarks\benchmarks.fsproj", "{C5DF6347-D612-466B-B038-69474A35B51E}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "build", "build\build.fsproj", "{18220329-75D6-4C30-BEEF-9401325F85EC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -148,6 +152,42 @@ Global
{5DED3CA8-B331-4B48-A6A2-2EE1410437CA}.Release|x64.Build.0 = Release|Any CPU
{5DED3CA8-B331-4B48-A6A2-2EE1410437CA}.Release|x86.ActiveCfg = Release|Any CPU
{5DED3CA8-B331-4B48-A6A2-2EE1410437CA}.Release|x86.Build.0 = Release|Any CPU
{AE58E4D7-57CC-413A-B566-1EE78C768B7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AE58E4D7-57CC-413A-B566-1EE78C768B7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AE58E4D7-57CC-413A-B566-1EE78C768B7A}.Debug|x64.ActiveCfg = Debug|Any CPU
{AE58E4D7-57CC-413A-B566-1EE78C768B7A}.Debug|x64.Build.0 = Debug|Any CPU
{AE58E4D7-57CC-413A-B566-1EE78C768B7A}.Debug|x86.ActiveCfg = Debug|Any CPU
{AE58E4D7-57CC-413A-B566-1EE78C768B7A}.Debug|x86.Build.0 = Debug|Any CPU
{AE58E4D7-57CC-413A-B566-1EE78C768B7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AE58E4D7-57CC-413A-B566-1EE78C768B7A}.Release|Any CPU.Build.0 = Release|Any CPU
{AE58E4D7-57CC-413A-B566-1EE78C768B7A}.Release|x64.ActiveCfg = Release|Any CPU
{AE58E4D7-57CC-413A-B566-1EE78C768B7A}.Release|x64.Build.0 = Release|Any CPU
{AE58E4D7-57CC-413A-B566-1EE78C768B7A}.Release|x86.ActiveCfg = Release|Any CPU
{AE58E4D7-57CC-413A-B566-1EE78C768B7A}.Release|x86.Build.0 = Release|Any CPU
{C5DF6347-D612-466B-B038-69474A35B51E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C5DF6347-D612-466B-B038-69474A35B51E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C5DF6347-D612-466B-B038-69474A35B51E}.Debug|x64.ActiveCfg = Debug|Any CPU
{C5DF6347-D612-466B-B038-69474A35B51E}.Debug|x64.Build.0 = Debug|Any CPU
{C5DF6347-D612-466B-B038-69474A35B51E}.Debug|x86.ActiveCfg = Debug|Any CPU
{C5DF6347-D612-466B-B038-69474A35B51E}.Debug|x86.Build.0 = Debug|Any CPU
{C5DF6347-D612-466B-B038-69474A35B51E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C5DF6347-D612-466B-B038-69474A35B51E}.Release|Any CPU.Build.0 = Release|Any CPU
{C5DF6347-D612-466B-B038-69474A35B51E}.Release|x64.ActiveCfg = Release|Any CPU
{C5DF6347-D612-466B-B038-69474A35B51E}.Release|x64.Build.0 = Release|Any CPU
{C5DF6347-D612-466B-B038-69474A35B51E}.Release|x86.ActiveCfg = Release|Any CPU
{C5DF6347-D612-466B-B038-69474A35B51E}.Release|x86.Build.0 = Release|Any CPU
{18220329-75D6-4C30-BEEF-9401325F85EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{18220329-75D6-4C30-BEEF-9401325F85EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{18220329-75D6-4C30-BEEF-9401325F85EC}.Debug|x64.ActiveCfg = Debug|Any CPU
{18220329-75D6-4C30-BEEF-9401325F85EC}.Debug|x64.Build.0 = Debug|Any CPU
{18220329-75D6-4C30-BEEF-9401325F85EC}.Debug|x86.ActiveCfg = Debug|Any CPU
{18220329-75D6-4C30-BEEF-9401325F85EC}.Debug|x86.Build.0 = Debug|Any CPU
{18220329-75D6-4C30-BEEF-9401325F85EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{18220329-75D6-4C30-BEEF-9401325F85EC}.Release|Any CPU.Build.0 = Release|Any CPU
{18220329-75D6-4C30-BEEF-9401325F85EC}.Release|x64.ActiveCfg = Release|Any CPU
{18220329-75D6-4C30-BEEF-9401325F85EC}.Release|x64.Build.0 = Release|Any CPU
{18220329-75D6-4C30-BEEF-9401325F85EC}.Release|x86.ActiveCfg = Release|Any CPU
{18220329-75D6-4C30-BEEF-9401325F85EC}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{E0466000-F8E4-416B-B605-C65F7602367A} = {E28025A7-EF6A-45BF-8FA0-75E394D3D42B}
Expand Down
108 changes: 108 additions & 0 deletions benchmarks/AsyncResultCE.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
namespace FsToolkit.ErrorHandling.Benchmarks

open System
open BenchmarkDotNet
open BenchmarkDotNet.Attributes
open FsToolkit.ErrorHandling
module AsyncResultCE =


type AsyncResultInlinedLambdaBuilder() =

member _.Return(value: 'T) : Async<Result<'T, 'TError>> = async.Return <| result.Return value

member inline _.ReturnFrom(asyncResult: Async<Result<'T, 'TError>>) : Async<Result<'T, 'TError>> = asyncResult

member _.Zero() : Async<Result<unit, 'TError>> = async.Return <| result.Zero()

member inline _.Bind
(
asyncResult: Async<Result<'T, 'TError>>,
[<InlineIfLambda>] binder: 'T -> Async<Result<'U, 'TError>>
) : Async<Result<'U, 'TError>> =
async.Bind(asyncResult, fun r ->
match r with
| Ok x -> binder x
| Error e -> Error e |> async.Return
)
member inline _.Delay([<InlineIfLambda>] generator: unit -> Async<Result<'T, 'TError>>) : Async<Result<'T, 'TError>> =
async.Delay generator

/// <summary>
/// Method lets us transform data types into our internal representation. This is the identity method to recognize the self type.
///
/// See https://stackoverflow.com/questions/35286541/why-would-you-use-builder-source-in-a-custom-computation-expression-builder
/// </summary>
member inline _.Source(result: Async<Result<_, _>>) : Async<Result<_, _>> = result
open AsyncResultCE




[<AutoOpen>]
// Having members as extensions gives them lower priority in
// overload resolution and allows skipping more type annotations.
module AsyncResultCEExtensions =

type AsyncResultInlinedLambdaBuilder with
/// <summary>
/// Needed to allow `for..in` and `for..do` functionality
/// </summary>
member inline _.Source(s: #seq<_>) = s

/// <summary>
/// Method lets us transform data types into our internal representation.
/// </summary>
member inline _.Source(result: Result<_, _>) : Async<Result<_, _>> = Async.singleton result
let rec fib n =
if n < 2L then n
else fib (n - 1L) + fib (n - 2L)

let rec afib (n, level) = async {
if n < 0L then return Error "No"
elif n < 2L then
return Ok n
elif n < level then
return Ok (fib n)
else
let! n2a = afib (n-2L, level) |> Async.StartChild
let! n1 = afib (n-1L, level)
let! n2 = n2a
match n1, n2 with
| Ok n1, Ok n2 ->
return Ok (n2 + n1)
| Error e, _
| _, Error e -> return Error e
}
let asyncResultInlinedIfLambda = AsyncResultInlinedLambdaBuilder()

[<MemoryDiagnoser>]
type AsyncResult_BindCEBenchmarks () =

[<Benchmark(Baseline = true)>]
member this.afib() =
afib(10,5)
|> Async.StartAsTask

[<Benchmark>]
member this.Result_Normal_Bind_CE() =
let action () = asyncResult {
let! a = Ok 10
let! b = Ok 5
let! c = afib(a, b)
return c
}
action ()
|> Async.StartAsTask


[<Benchmark>]
member this.Result_Alt_Inlined_Bind_CE () =
let action () = asyncResultInlinedIfLambda {
let! a = Ok 10
let! b = Ok 5
let! c = afib(a, b)
return c
}
action ()
|> Async.StartAsTask
Loading

0 comments on commit 69b0019

Please sign in to comment.