Java 和 C# 最大的不同是什么?
var x = new int[10];
fixed (int* p = x)
{
Console.WriteLine(*((long*)p - 1)); // 10
}
Console.WriteLine((long)typeof(int[]).TypeHandle.Value == *((long*)p - 2)); // True
var x = stackalloc int[2]; // 或者 Span<int> x = stackalloc int[2]; 做安全访存
x[0] = 3;
x[1] = 1;
Console.WriteLine(x[0] + x[1]); // 4
var array = (int*)NativeMemory.Alloc(10, sizeof(int));
array[0] = 1;
array[1] = 3;
Console.WriteLine(array[0] + array[1]); // 4
NativeMemory.Free(array);
var obj = new Foo();
obj.Float = 1;
Console.WriteLine(obj.Int); // 1065353216
Console.WriteLine(obj.Bytes[0]); // 0
Console.WriteLine(obj.Bytes[1]); // 0
Console.WriteLine(obj.Bytes[2]); // 128
Console.WriteLine(obj.Bytes[3]); // 63
[ ]
struct Foo
{
[public int Int; ]
[public float Float; ]
[public unsafe fixed byte Bytes[4]; ]
}
0x00111111100000000000000000000000
,以小端方式存储后占 4 个字节,分别是
0x00000000
、
0x00000000
、
0x10000000
、
0x00111111
。
var data = stackalloc byte[] { 0, 0, 128, 63 };
var foo = Unsafe.AsRef<Foo>(data);
Console.WriteLine(foo.Float); // 1
[ ]
struct Foo
{
[public int Int; ]
[public float Float; ]
[public unsafe fixed byte Bytes[4]; ]
}
var data = 1065353216;
var foo = Unsafe.AsRef<Foo>(&data);
Console.WriteLine(foo.Float); // 1
[ ]
struct Foo
{
[public int Int; ]
[public float Float; ]
[public unsafe fixed byte Bytes[4]; ]
}
var data = new byte[] { 0, 0, 128, 63 };
fixed (void* p = data)
{
var foo = Unsafe.AsRef<Foo>(p);
Console.WriteLine(foo.Float); // 1
}
[ ]
struct Foo
{
[public int Int; ]
[public float Float; ]
[public unsafe fixed byte Bytes[4]; ]
}
extern "C" __declspec(dllexport)
char* __cdecl foo(char* (*gen)(int), int count) {
return gen(count);
}
[ ]
static extern string Foo(delegate* unmanaged[Cdecl]<int, nint> gen, int count);
[typeof(CallConvCdecl) }), SuppressGCTransition] ] {
static nint Generate(int count)
{
var str = Enumerable.Repeat("w", count).Aggregate((a, b) => $"{a}{b}");
return Marshal.StringToHGlobalAnsi(str);
}
var f = (delegate* unmanaged[Cdecl]<int, nint>)&Generate;
var result = Foo(f, 5);
Console.WriteLine(result); // wwwww
[typeof(CallConvCdecl) }), SuppressGCTransition] ] {
static nint Generate(int count)
{
var str = Enumerable.Repeat("w", count).Aggregate((a, b) => $"{a}{b}");
return Marshal.StringToHGlobalAnsi(str);
}
var f = (delegate* unmanaged[Cdecl]<int, nint>)&Generate;
var library = NativeLibrary.Load("./foo.dll");
var foo = (delegate* unmanaged[Cdecl, SuppressGCTransition]<delegate* unmanaged[Cdecl]<int, nint>, int, string>)NativeLibrary.GetExport(library, "foo");
var result = foo(f, 5);
Console.WriteLine(result); // wwwww
NativeLibrary.Free(library);
var vec1 = Vector128.Create(1.1f, 2.2f, 3.3f, 4.4f);
var vec2 = Vector128.Create(5.5f, 6.6f, 7.7f, 8.8f);
Console.WriteLine(Calc(vec1, vec2));
float Calc(Vector128<float> l, Vector128<float> r)
{
if (Avx2.IsSupported)
{
var result = Avx2.Multiply(l, r);
float sum = 0;
for (var i = 0; i < Vector128<float>.Count; i++) sum += result.GetElement(i);
return sum;
}
else if (Rdm.IsSupported)
{
var result = Rdm.Multiply(l, r);
float sum = 0;
for (var i = 0; i < Vector128<float>.Count; i++) sum += result.GetElement(i);
return sum;
}
else
{
float sum = 0;
for (int i = 0; i < Vector128<float>.Count; i++)
{
sum += l.GetElement(i) * r.GetElement(i);
}
return sum;
}
}
vzeroupper
vmovupd xmm0, [r8]
vmulps xmm0, xmm0, [r8+0x10]
vmovaps xmm1, xmm0
vxorps xmm2, xmm2, xmm2
vaddss xmm1, xmm1, xmm2
vmovshdup xmm2, xmm0
vaddss xmm1, xmm2, xmm1
vunpckhps xmm2, xmm0, xmm0
vaddss xmm1, xmm2, xmm1
vshufps xmm0, xmm0, xmm0, 0xff
vaddss xmm1, xmm0, xmm1
vmovaps xmm0, xmm1
ret
float Calc(Vector128<float> l, Vector128<float> r)
{
float sum = 0;
for (int i = 0; i < Vector128<float>.Count; i++)
{
sum += l.GetElement(i) * r.GetElement(i);
}
return sum;
}
void Test(in Foo v) { }
struct Foo
{
public long A, B, C, D, E, F, G, H, I, J, K, L, M, N;
}
double Test(int x1, int y1, int x2, int y2)
{
var p1 = new Point(x1, y1);
var p2 = new Point(x2, y2);
return GetDistance(p1, p2);
}
[ ]
double GetDistance(Point a, Point b)
{
return Math.Sqrt((a.X - b.X) * (a.X - b.X) + (a.Y - b.Y) * (a.Y - b.Y));
}
struct Point
{
public Point(int x, int y)
{
X = x; Y = y;
}
public int X { get; set; }
public int Y { get; set; }
}
vzeroupper sub ecx, r8dmov eax, ecximul eax, ecxsub edx, r9dmov ecx, edximul edx, ecxadd eax, edxvxorps xmm0, xmm0, xmm0vcvtsi2sd xmm0, xmm0, eaxvsqrtsd xmm0, xmm0, xmm0ret
var vec = new Vector(10);
vec[2] = 5;
Console.WriteLine(vec[2]); // 5
ref var x = ref vec[3];
x = 7;
Console.WriteLine(vec[3]); // 7
class Vector
{
private int[] _array;
public Vector(int count) => _array = new int[count];
public ref int this[int index] => ref _array[index];
}
var vec = new Vector(10);
vec[2] = 5;
Console.WriteLine(vec[2]); // 5
ref var x = ref vec[3];
x = 7;
Console.WriteLine(vec[3]); // 7
unsafe class Vector
{
private int* _memory;
public Vector(uint count) => _memory = (int*)NativeMemory.Alloc(count, sizeof(int));
public ref int this[int index] => ref _memory[index];
~Vector() => NativeMemory.Free(_memory);
}
double Test1(double x1, double y1, double x2, double y2)
{
var p1 = new Point<double>(x1, y1);
var p2 = new Point<double>(x2, y2);
var result = GetDistanceSquare(p1, p2);
return Math.Sqrt(result);
}
double Test2(int x1, int y1, int x2, int y2)
{
var p1 = new Point<int>(x1, y1);
var p2 = new Point<int>(x2, y2);
var result = GetDistanceSquare(p1, p2);
return Math.Sqrt(result);
}
[ ]
T GetDistanceSquare<T>(Point<T> a, Point<T> b) where T : struct, IBinaryNumber<T>
{
return (a.X - b.X) * (a.X - b.X) + (a.Y - b.Y) * (a.Y - b.Y);
}
struct Point<T> where T : struct, IBinaryNumber<T>
{
public Point(T x, T y)
{
X = x; Y = y;
}
public T X { get; set; }
public T Y { get; set; }
}
Test1
vzeroupper
vsubsd xmm0, xmm0, xmm2
vmovaps xmm2, xmm0
vmulsd xmm0, xmm0, xmm2
vsubsd xmm1, xmm1, xmm3
vmovaps xmm2, xmm1
vmulsd xmm1, xmm1, xmm2
vaddsd xmm0, xmm1, xmm0
vsqrtsd xmm0, xmm0, xmm0
ret
Test2
vzeroupper
sub ecx, r8d
mov eax, ecx
imul eax, ecx
sub edx, r9d
mov ecx, edx
imul edx, ecx
add eax, edx
vxorps xmm0, xmm0, xmm0
vcvtsi2sd xmm0, xmm0, eax
vsqrtsd xmm0, xmm0, xmm0
ret
GC.TryStartNoGCRegion(1024 * 1024 * 128);
GC.TryStartNoGCRegion(1024 * 1024 * 128, true);
GC.EndNoGCRegion();
GCSettings.LatencyMode = GCLatencyMode.Batch;
GCSettings.LatencyMode = GCLatencyMode.Interactive;
GCSettings.LatencyMode = GCLatencyMode.LowLatency;
GCSettings.LatencyMode = GCLatencyMode.NoGCRegion;
GCSettings.LatencyMode = GCLatencyMode.SustainedLowLatency;
var kernel32 = NativeLibrary.Load("kernel32.dll");
var virtualProtectEx = (delegate* unmanaged[Cdecl, SuppressGCTransition]<nint, void*, nint, int, out int, bool>)NativeLibrary.GetExport(kernel32, "VirtualProtectEx");
var processHandle = Process.GetCurrentProcess().Handle;
Memory<byte> code = new byte[] {
0x8d, 0x04, 0x11, // lea rax, [rcx+rdx]
0xc3 // ret
}
using (var handle = code.Pin())
{
virtualProtectEx(processHandle, handle.Pointer, code.Length, 0x40, out _);
var f = (delegate*<int, int, int>)handle.Pointer;
Console.WriteLine(f(2, 3)); // 5
}
virtualProtectEx = null;
NativeLibrary.Free(kernel32);
链接:https://www.zhihu.com/question/20451584/answer/2220757276
来源:知乎