|
#nowarn "9" |
|
|
|
open System |
|
open System.Globalization |
|
open Microsoft.FSharp.NativeInterop |
|
open BenchmarkDotNet.Attributes |
|
open BenchmarkDotNet.Running |
|
|
|
let inline private stackalloc<'a when 'a: unmanaged> size = |
|
let p = NativePtr.stackalloc<'a> size |> NativePtr.toVoidPtr |
|
Span<'a>(p, size) |
|
|
|
let inline hexToDec(hex: byte) = |
|
if hex > '9'B then |
|
hex - 'a'B + 10uy |
|
else |
|
hex - '0'B |
|
|
|
let inline hexToInt64 (bytes: ReadOnlySpan<byte>) = |
|
let mutable x = 0L |
|
let last = bytes.Length - 1 |
|
for i = 0 to last do |
|
x <- x + (int64(hexToDec bytes.[i]) <<< 4*(last - i)) |
|
x |
|
|
|
let inline hexTo (f: byte-> ^a) (bytes: ReadOnlySpan<byte>): ^a = |
|
let mutable x = LanguagePrimitives.GenericZero |
|
let last = bytes.Length - 1 |
|
for i = 0 to last do |
|
x <- x + (f(hexToDec bytes.[i]) <<< 4*(last - i)) |
|
x |
|
|
|
[<MemoryDiagnoser>] |
|
type Tests() = |
|
|
|
member _.Data() = seq { |
|
"243c104b2d800"B |
|
} |
|
|
|
[<Benchmark(Baseline = true)>] |
|
[<ArgumentsSource("Data")>] |
|
member _.HexToInt64(bytes: array<byte>) = |
|
hexToInt64 (ReadOnlySpan(bytes)) |
|
|
|
[<Benchmark>] |
|
[<ArgumentsSource("Data")>] |
|
member _.HexToInt64Generic(bytes: array<byte>) = |
|
hexTo int64 (ReadOnlySpan(bytes)) |
|
|
|
[<Benchmark>] |
|
[<ArgumentsSource("Data")>] |
|
member _.ConvertToInt64(bytes: array<byte>) = |
|
let a = Text.Encoding.UTF8.GetString(ReadOnlySpan(bytes)) |
|
Convert.ToInt64(a, 16) |
|
|
|
[<Benchmark>] |
|
[<ArgumentsSource("Data")>] |
|
member _.Int64Parse(bytes: array<byte>) = |
|
let a = Text.Encoding.UTF8.GetString(ReadOnlySpan(bytes)) |
|
Int64.Parse(a, NumberStyles.HexNumber, CultureInfo.InvariantCulture) |
|
|
|
[<Benchmark>] |
|
[<ArgumentsSource("Data")>] |
|
member _.Int64ParseAllocFree(bytes: array<byte>) = |
|
let input = ReadOnlySpan(bytes) |
|
let a = stackalloc<char> bytes.Length |
|
for i = 0 to bytes.Length - 1 do |
|
a.[i] <- char(input.[i]) |
|
Int64.Parse(Span.op_Implicit a, NumberStyles.HexNumber, CultureInfo.InvariantCulture) |
|
|
|
[<EntryPoint>] |
|
let main argv = |
|
BenchmarkRunner.Run<Tests>() |> ignore |
|
|
|
let t = Tests() |
|
let bytes = t.Data() |> Seq.head |
|
t.HexToInt64 bytes |> Console.WriteLine |
|
t.HexToInt64Generic bytes |> Console.WriteLine |
|
t.ConvertToInt64 bytes |> Console.WriteLine |
|
t.Int64Parse bytes |> Console.WriteLine |
|
t.Int64ParseAllocFree bytes |> Console.WriteLine |
|
|
|
0 |