Skip to content

Instantly share code, notes, and snippets.

@Tornhoof
Last active April 5, 2018 06:41
Show Gist options
  • Save Tornhoof/7bac156e3b664e3bef36f236de21cf42 to your computer and use it in GitHub Desktop.
Save Tornhoof/7bac156e3b664e3bef36f236de21cf42 to your computer and use it in GitHub Desktop.
Benchmark Integer Formatting
using System;
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
namespace FormatIntegerPerformance
{
class Program
{
static void Main(string[] args)
{
BenchmarkRunner.Run<Benchmark>();
}
}
[MemoryDiagnoser]
public class Benchmark
{
const int Number = 123456789;
private static readonly NumberFormatter Formatter = new NumberFormatter();
[Benchmark(Description = "Integer Formatting in CoreCLR")]
public string CoreClr()
{
Span<char> span = stackalloc char[21];
int pos = 0;
Formatter.WriteInt64CoreClr(span, ref pos, Number);
return span.Slice(0, pos).ToString();
}
[Benchmark(Description = "Integer Formatting in Utf8Json")]
public string Utf8Json()
{
Span<char> span = stackalloc char[21];
int pos = 0;
Formatter.WriteInt64Utf8Json(span, ref pos, Number);
return span.Slice(0, pos).ToString();
}
[Benchmark(Description = "Integer Formatting in System.Buffeers.Text.Utf8Formatter")]
public byte[] Utf8Formatter()
{
var result = new byte[21];
Span<byte> span = result;
System.Buffers.Text.Utf8Formatter.TryFormat(Number, span, out var written);
return result;
}
}
public class NumberFormatter
{
public void WriteInt64Utf8Json(Span<char> chars, ref int pos, long value)
{
if (value < 0)
{
chars[pos++] = '-';
value = unchecked(-value);
}
WriteUInt64(chars.Slice(pos), ref pos, (ulong)value);
}
public void WriteInt64CoreClr(Span<char> chars, ref int pos, long value)
{
value.TryFormat(chars.Slice(pos), out var written);
pos += written;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
// https://github.com/neuecc/Utf8Json/blob/master/src/Utf8Json/Internal/NumberConverter.cs
// or https://stackoverflow.com/questions/4351371/c-performance-challenge-integer-to-stdstring-conversion
private void WriteUInt64(Span<char> chars, ref int pos, ulong value)
{
var num1 = value;
ulong div;
if (num1 < 10000)
{
if (num1 < 10)
{
goto L1;
}
if (num1 < 100)
{
goto L2;
}
if (num1 < 1000)
{
goto L3;
}
goto L4;
}
else
{
var num2 = num1 / 10000;
num1 -= num2 * 10000;
if (num2 < 10000)
{
if (num2 < 10)
{
goto L5;
}
if (num2 < 100)
{
goto L6;
}
if (num2 < 1000)
{
goto L7;
}
goto L8;
}
else
{
var num3 = num2 / 10000;
num2 -= num3 * 10000;
if (num3 < 10000)
{
if (num3 < 10)
{
goto L9;
}
if (num3 < 100)
{
goto L10;
}
if (num3 < 1000)
{
goto L11;
}
goto L12;
}
else
{
var num4 = num3 / 10000;
num3 -= num4 * 10000;
if (num4 < 10000)
{
if (num4 < 10)
{
goto L13;
}
if (num4 < 100)
{
goto L14;
}
if (num4 < 1000)
{
goto L15;
}
goto L16;
}
else
{
var num5 = num4 / 10000;
num4 -= num5 * 10000;
if (num5 < 10000)
{
if (num5 < 10)
{
goto L17;
}
if (num5 < 100)
{
goto L18;
}
if (num5 < 1000)
{
goto L19;
}
goto L20;
}
L20:
chars[pos++] = (char)('0' + (div = (num5 * 8389L) >> 23));
num5 -= div * 1000;
L19:
chars[pos++] = (char)('0' + (div = (num5 * 5243L) >> 19));
num5 -= div * 100;
L18:
chars[pos++] = (char)('0' + (div = (num5 * 6554L) >> 16));
num5 -= div * 10;
L17:
chars[pos++] = (char)('0' + (num5));
}
L16:
chars[pos++] = (char)('0' + (div = (num4 * 8389L) >> 23));
num4 -= div * 1000;
L15:
chars[pos++] = (char)('0' + (div = (num4 * 5243L) >> 19));
num4 -= div * 100;
L14:
chars[pos++] = (char)('0' + (div = (num4 * 6554L) >> 16));
num4 -= div * 10;
L13:
chars[pos++] = (char)('0' + (num4));
}
L12:
chars[pos++] = (char)('0' + (div = (num3 * 8389L) >> 23));
num3 -= div * 1000;
L11:
chars[pos++] = (char)('0' + (div = (num3 * 5243L) >> 19));
num3 -= div * 100;
L10:
chars[pos++] = (char)('0' + (div = (num3 * 6554L) >> 16));
num3 -= div * 10;
L9:
chars[pos++] = (char)('0' + (num3));
}
L8:
chars[pos++] = (char)('0' + (div = (num2 * 8389L) >> 23));
num2 -= div * 1000;
L7:
chars[pos++] = (char)('0' + (div = (num2 * 5243L) >> 19));
num2 -= div * 100;
L6:
chars[pos++] = (char)('0' + (div = (num2 * 6554L) >> 16));
num2 -= div * 10;
L5:
chars[pos++] = (char)('0' + (num2));
}
L4:
chars[pos++] = (char)('0' + (div = (num1 * 8389L) >> 23));
num1 -= div * 1000;
L3:
chars[pos++] = (char)('0' + (div = (num1 * 5243L) >> 19));
num1 -= div * 100;
L2:
chars[pos++] = (char)('0' + (div = (num1 * 6554L) >> 16));
num1 -= div * 10;
L1:
chars[pos++] = (char)('0' + (num1));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment