Skip to content

Instantly share code, notes, and snippets.

@vexx32
Created October 4, 2018 15:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vexx32/1dc212180b87ecedd6fbcd81b8aa46f8 to your computer and use it in GitHub Desktop.
Save vexx32/1dc212180b87ecedd6fbcd81b8aa46f8 to your computer and use it in GitHub Desktop.
benchmark for binary parsing in PS Core
///////////////////////////////////////
////////// BENCHMARK RESULTS //////////
///////////////////////////////////////
// * Summary *
BenchmarkDotNet=v0.11.1, OS=Windows 10.0.17134.286 (1803/April2018Update/Redstone4)
Intel Core i3-3240 CPU 3.40GHz (Ivy Bridge), 1 CPU, 4 logical and 2 physical cores
Frequency=3312801 Hz, Resolution=301.8594 ns, Timer=TSC
.NET Core SDK=2.1.402
[Host] : .NET Core 2.1.4 (CoreCLR 4.6.26814.03, CoreFX 4.6.26814.02), 64bit RyuJIT
Core : .NET Core 2.1.4 (CoreCLR 4.6.26814.03, CoreFX 4.6.26814.02), 64bit RyuJIT
Job=Core Runtime=Core
Method | Mean | Error | StdDev | Gen 0 | Allocated |
----------------- |-----------:|-----------:|----------:|-------:|----------:|
ParseWithSpans | 8,716.7 ns | 178.832 ns | 527.29 ns | 2.2430 | 3552 B |
ParseWithConvert | 209.1 ns | 4.222 ns | 10.67 ns | 0.0558 | 88 B |
// * Warnings *
MultimodalDistribution
BinaryParse.ParseWithConvert: Core -> It seems that the distribution can have several modes (mValue = 3.13)
// * Legends *
Mean : Arithmetic mean of all measurements
Error : Half of 99.9% confidence interval
StdDev : Standard deviation of all measurements
Gen 0 : GC Generation 0 collects per 1k Operations
Allocated : Allocated memory per single operation (managed only, inclusive, 1KB = 1024B)
1 ns : 1 Nanosecond (0.000000001 sec)
// * Diagnostic Output - MemoryDiagnoser *
// ***** BenchmarkRunner: End *****
Run time: 00:02:27 (147.79 sec), executed benchmarks: 2
// * Artifacts cleanup *
///////////////////////////////////////
/////// CODE USED FOR BENCHMARK ///////
///////////////////////////////////////
using System;
using System.Numerics;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
namespace Benchmark
{
[CoreJob]
[MemoryDiagnoser]
public class BinaryParse
{
private static Random random = new Random();
private readonly string data;
public BinaryParse()
{
data = Convert.ToString(random.Next(), 2);
}
[Benchmark]
public BigInteger ParseWithSpans() => ParseBinarySpans(data);
[Benchmark]
public BigInteger ParseWithConvert() => ParseBinaryStrings(data);
internal static BigInteger ParseBinarySpans(ReadOnlySpan<char> digits)
{
bool unsigned = false;
switch (digits.Length)
{
case int n when (n <= 8):
return parseBinarySpans(digits, unsigned, 8);
case int n when (n <= 16):
return parseBinarySpans(digits, unsigned, 16);
case int n when (n <= 32):
return parseBinarySpans(digits, unsigned, 32);
case int n when (n <= 64):
return parseBinarySpans(digits, unsigned, 64);
default:
return parseBinarySpans(digits, unsigned);
}
}
private static BigInteger parseBinarySpans(ReadOnlySpan<char> digits, bool unsigned, int padLength = 0)
{
unsigned = unsigned || (digits[0] == '0') || digits.Length < padLength;
BigInteger value = 0;
for (int i = 0; i < digits.Length; i++)
{
value += (digits[i] == '1') ? BigInteger.Pow(2, digits.Length - i - 1) : 0;
}
return unsigned ? value : (value - BigInteger.Pow(2, digits.Length));
}
internal static BigInteger ParseBinaryStrings(ReadOnlySpan<char> digits)
{
bool unsigned = false;
var digitString = new string(digits);
switch (digits.Length)
{
case int n when (n <= 8):
return unsigned ? (BigInteger)Convert.ToByte(digitString, 2) : Convert.ToSByte(digitString, 2);
case int n when (n <= 16):
return unsigned ? (BigInteger)Convert.ToUInt16(digitString, 2) : Convert.ToInt16(digitString, 2);
case int n when (n <= 32):
return unsigned ? (BigInteger)Convert.ToUInt32(digitString, 2) : Convert.ToInt32(digitString, 2);
case int n when (n <= 64):
return unsigned ? (BigInteger)Convert.ToUInt64(digitString, 2) : Convert.ToInt64(digitString, 2);
default:
return ParseBigBinary(digits, unsigned);
}
}
private static BigInteger ParseBigBinary(ReadOnlySpan<char> digits, bool unsigned)
{
BigInteger value = 0;
unsigned = unsigned || (digits[0] == '0');
for (int i = 0; i < digits.Length; i++)
{
value += (digits[i] == '1') ? BigInteger.Pow(2, digits.Length - i - 1) : 0;
}
return unsigned ? value : (value - BigInteger.Pow(2, digits.Length));
}
}
public class Program
{
public static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<BinaryParse>();
}
}
}
///////////////////////////////////////
///// END CODE USED FOR BENCHMARK /////
///////////////////////////////////////
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment