Skip to content

Instantly share code, notes, and snippets.

@buybackoff
Last active April 11, 2021 20:54
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 buybackoff/e2f92cfb35f7e7ea32e2ea9afb4298ee to your computer and use it in GitHub Desktop.
Save buybackoff/e2f92cfb35f7e7ea32e2ea9afb4298ee to your computer and use it in GitHub Desktop.
ByRefCtor
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace ByRefCtor
{
public readonly struct Test
{
private static ref TestMut AsMutable(ref Test d) => ref Unsafe.As<Test, TestMut>(ref d);
public readonly long _value;
public readonly long _value1;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Test(double value)
{
TestMut.Init(value, out this);
}
private struct TestMut
{
private long _value;
private long _value1;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Init(double input, out Test mut)
{
Unsafe.SkipInit(out mut);
Unsafe.As<Test, TestMut>(ref mut)._value = (long) input;
Unsafe.As<Test, TestMut>(ref mut)._value1 = ((long) input) >> 1;
}
}
}
public readonly struct Test1
{
private static ref TestMut1 AsMutable(ref Test1 d) => ref Unsafe.As<Test1, TestMut1>(ref d);
public readonly long _value;
public readonly long _value1;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Test1(double value)
{
this = default;
TestMut1.Init(value, ref AsMutable(ref this));
}
private struct TestMut1
{
private long _value;
private long _value1;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Init(double input, ref TestMut1 test)
{
test._value = (long) input;
test._value1 = ((long) input) >> 1;
}
}
}
class Program
{
static void Main(string[] args)
{
var count = 1000_000_000;
for (int r = 0; r < 10; r++)
{
RunTest(count);
RunTest1(count);
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static void RunTest(int count)
{
long sum;
Stopwatch sw;
sum = 0;
sw = Stopwatch.StartNew();
for (int i = 0; i < count; i++)
{
sum += new Test(i)._value;
}
sw.Stop();
Console.WriteLine($"Test: {sw.ElapsedMilliseconds}");
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static void RunTest1(int count)
{
long sum;
Stopwatch sw;
sum = 0;
sw = Stopwatch.StartNew();
for (int i = 0; i < count; i++)
{
sum += new Test1(i)._value;
}
sw.Stop();
Console.WriteLine($"Test1: {sw.ElapsedMilliseconds}");
}
}
}
using System;
using System.Runtime.CompilerServices;
namespace ByRefCtor
{
public readonly struct Test
{
private static ref TestMut AsMutable(ref Test d) => ref Unsafe.As<Test, TestMut>(ref d);
private readonly long _value;
public Test(double value)
{
// `ref this` works here: https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Decimal.cs#L166-L176
TestMut.Init(value, out AsMutable(ref this));
}
private struct TestMut
{
private long _value;
public static void Init(double input, out TestMut mut)
{
mut = default;
mut._value = (long) input;
}
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
using System;
using System.Runtime.CompilerServices;
namespace ByRefCtor
{
public readonly struct Test
{
private static ref TestMut AsMutable(ref Test d) => ref Unsafe.As<Test, TestMut>(ref d);
private readonly long _value;
public Test(double value)
{
TestMut.Init(value, out this);
}
private struct TestMut
{
private long _value;
public static void Init(double input, out Test mut)
{
Unsafe.SkipInit(out mut);
Unsafe.As<Test, TestMut>(ref mut)._value = (long) input;
}
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment