Created
February 17, 2022 17:53
-
-
Save thinkbeforecoding/1d07315cfb21ee779f5b75a497773731 to your computer and use it in GitHub Desktop.
StackStack
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
| Method | Mean | Error | StdDev | Ratio | RatioSD | | |
|-------------- |---------:|--------:|--------:|------:|--------:| | |
| UseSpan | 241.7 ns | 2.98 ns | 2.64 ns | 1.00 | 0.00 | | |
| UseCollection | 403.4 ns | 5.58 ns | 5.22 ns | 1.67 | 0.03 | |
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
// Learn more about F# at http://docs.microsoft.com/dotnet/fsharp | |
open System | |
open BenchmarkDotNet.Attributes | |
open BenchmarkDotNet.Running | |
// Define a function to construct a message to print | |
#nowarn "9" "42" | |
open System.Runtime.CompilerServices | |
let inline stackalloc<'t> n = Span<'t>( (# "localloc" (n*sizeof<'t>) : voidptr #), n) | |
[<Struct;IsByRefLike>] | |
type StackStack<'t> = | |
{ Span: Span<'t> | |
mutable Index: int} | |
module StackStack = | |
let inline create<'t> n = | |
{ Span = stackalloc<int64> n; Index = 0 } | |
let inline pop (stack: StackStack<'t> byref) = | |
stack.Index <- stack.Index-1 | |
stack.Span[stack.Index] | |
let inline push value (stack: StackStack<'t> byref) = | |
stack.Span[stack.Index] <- value | |
stack.Index <- stack.Index+1 | |
open System.Collections.Generic | |
[<RyuJitX64Job>] | |
type StackBench() = | |
let rec algo n (stack: StackStack<int64> byref) = | |
if n > 0 then | |
StackStack.push (int64 n) &stack | |
algo (n-1) &stack | |
let dowork() = | |
let mutable stack = StackStack.create 256 | |
algo 100 &stack | |
let mutable result = 0L | |
for _ in 0 .. 99 do | |
result <- result + StackStack.pop &stack | |
result | |
let stack = Stack<int64>(256) | |
let rec algo' n = | |
if n > 0 then | |
stack.Push (int64 n) | |
algo' (n-1) | |
let dowork'() = | |
stack.Clear() | |
algo' 100 | |
let mutable result = 0L | |
for i in 0 .. 99 do | |
result <- result + stack.Pop() | |
result | |
[<Benchmark(Baseline = true)>] | |
member _.UseSpan() = | |
dowork() | |
[<Benchmark()>] | |
member _.UseCollection() = | |
dowork'() | |
let defaultSwitch () = BenchmarkSwitcher [| typeof<StackBench>|] | |
[<EntryPoint>] | |
let main argv = | |
let sumarry = defaultSwitch().Run argv | |
0 // return an integer exit code |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'm curious why you define a function for stack allocating that emits IL instead of using built-in methods. Is there a reason for this?