Skip to content

Instantly share code, notes, and snippets.

@slang25
Forked from cartermp/sb-bench.fs
Last active November 24, 2021 11:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save slang25/ea89d25d3905f0047c9cf7b35b0bd99a to your computer and use it in GitHub Desktop.
Save slang25/ea89d25d3905f0047c9cf7b35b0bd99a to your computer and use it in GitHub Desktop.
// Learn more about F# at http://fsharp.org
open System
open System.Text
open System.Collections.Generic
open System.Linq
open BenchmarkDotNet.Attributes
open BenchmarkDotNet.Running
module Strings =
let private chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
let getNewString (rnd: Random) =
let len = rnd.Next() % 25
let chars = Enumerable.Repeat(chars, len).Select(fun s -> s.[rnd.Next(s.Length)]).ToArray()
String(chars)
[<AutoOpenAttribute>]
module StringBuffer =
type StringBuffer = StringBuilder -> unit
type StringBufferBuilder () =
member inline __.Yield (txt: string) = fun (b: StringBuilder) -> b.Append txt |> ignore
member inline __.Yield (c: char) = fun (b: StringBuilder) -> b.Append c |> ignore
member inline __.Yield (strings: #seq<string>) =
fun (b: StringBuilder) -> for s in strings do s |> b.AppendLine |> ignore
member inline __.YieldFrom (f: StringBuffer) = f
member __.Combine (f, g) = fun (b: StringBuilder) -> f b; g b
member __.Delay f = fun (b: StringBuilder) -> (f()) b
member __.Zero () = ignore
member __.For (xs: 'a seq, f: 'a -> StringBuffer) =
fun (b: StringBuilder) ->
let e = xs.GetEnumerator ()
while e.MoveNext() do
(f e.Current) b
member __.While (p: unit -> bool, f: StringBuffer) =
fun (b: StringBuilder) -> while p () do f b
member __.Run (f: StringBuffer) =
let b = StringBuilder()
do f b
b.ToString()
let stringBuffer = new StringBufferBuilder ()
[<MemoryDiagnoser>]
type Bench() =
let rnd = new Random()
let times = 1_0_000
let inputs = Array.init times (fun _ -> Strings.getNewString rnd)
[<Benchmark(Baseline=true)>]
member __.Concats() =
let mutable acc = String.Empty
for i in 0 .. times-1 do
acc <- acc + inputs.[i]
[<Benchmark>]
member __.StringBuilder() =
let sb = StringBuilder()
for i in 0 .. times-1 do
inputs.[i]
|> sb.Append
|> ignore
[<BenchmarkAttribute>]
member __.CompExpr() =
stringBuffer {
for i in 0 .. times-1 -> inputs.[i]
} |> ignore
[<EntryPoint>]
let main argv =
let summary = BenchmarkRunner.Run<Bench>()
printfn "%A" summary
0 // return an integer exit code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment