Skip to content

Instantly share code, notes, and snippets.

@pimbrouwers
Created August 17, 2022 17:56
Show Gist options
  • Save pimbrouwers/02271cc3337cc9ebe671ed42d04a0b92 to your computer and use it in GitHub Desktop.
Save pimbrouwers/02271cc3337cc9ebe671ed42d04a0b92 to your computer and use it in GitHub Desktop.
open System
open System.Text
[<AbstractClass; Sealed>]
type StringBuilderCache private () =
// The value 360 was chosen in discussion with performance experts as a compromise between using
// as litle memory (per thread) as possible and still covering a large part of short-lived
// StringBuilder creations on the startup path of VS designers.
[<Literal>]
static let _maxBuilderSize = 360
// == StringBuilder.DefaultCapacity
[<Literal>]
static let _defaultCapacity = 16
[<ThreadStatic; DefaultValue>]
static val mutable private cachedInstance : StringBuilder
static member Acquire (?capacity : int) =
let capacity' = defaultArg capacity _defaultCapacity
let sb = StringBuilderCache.cachedInstance
// Avoid stringbuilder block fragmentation by getting a new StringBuilder
// when the requested size is larger than the current capacity
if capacity' <= _maxBuilderSize &&
not(isNull sb) &&
capacity' <= sb.Capacity then
StringBuilderCache.cachedInstance <- null
sb.Clear() |> ignore
sb
else
new StringBuilder(capacity')
static member GetString (sb : StringBuilder) =
let result = sb.ToString()
if sb.Capacity <= _maxBuilderSize then StringBuilderCache.cachedInstance <- sb
result
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment