基本上我正在尝试从坐标中构建一个独特的64位ID,然后稍后可以将其拆分。这些操作将在短时间内执行数十亿次,因此速度至关重要。以下是我想要的:我有4个32位整数,但只有底部16位相关。我想将底部16位连接成一个64位的“长整型”(由于位相同,因此是否带符号并不重要)。所以如果我有:
largeId = 0000 0000 0000 0000 0000 0000 1000 1000
x = 0000 0000 0000 0000 0000 0000 1100 1100
y = 0000 0000 0000 0000 0000 0000 1110 1110
z = 0000 0000 0000 0000 0000 0000 1111 1111
它将变成:
Id = 0000 0000 1000 1000 0000 0000 1100 1100 0000 0000 1110 1110 0000 0000 1111 1111
我已经写了几个例程来产生所需的结果(即构建和拆分),并使用500^3迭代进行计时,以尝试找到最快的例程。将64位数字解码回4个int变量的例程运行时间约为编码所需时间的43%。如何加速编码? 例程:(根据Paul Smith的建议更新了多个变体)
public static long GetCombinedId(int largeId, int x, int y, int z)
{
var _largeId = (long)largeId;
var _x = (long)x;
var _y = (long)y;
var _z = (long)z;
return (_largeId << 48) | (_x << 32) | (_y << 16) | _z;
}
public static long GetCombinedId2(int largeId, int x, int y, int z)
{
return ((long)largeId << 48) | ((long)x << 32) | ((long)y << 16) | (long)z;
}
public static long GetCombinedId3(int largeId, int x, int y, int z)
{
unchecked
{
return ((long)(largeId << 16 | x) << 32) | (y << 16 | z );
}
}
public static void GetCoordinates(long id, out int largeId, out int x, out int y, out int z)
{
largeId = (int)(id >> 48);
x = (int)((id >> 32) & 0x0000_0000_0000_FFFF);
y = (int)((id >> 16) & 0x0000_0000_0000_FFFF);
z = (int)(id & 0x0000_0000_0000_FFFF);
}
public static void GetCoordinates2(long id, out int largeId, out int x, out int y, out int z)
{
largeId = (int)(id >> 48);
x = (int)((id << 16 ) >> 48);
y = (int)((id << 32 ) >> 48);
z = (int)((id << 48 ) >> 48);
}
保罗·史密斯技术的变体见答案部分描述
[StructLayout(LayoutKind.Explicit)]
public struct Mapper
{
[FieldOffset(0)] public Int64 Combined;
[FieldOffset(0)] public Int16 Short0;
[FieldOffset(2)] public Int16 Short1;
[FieldOffset(4)] public Int16 Short2;
[FieldOffset(6)] public Int16 Short3;
}
public static long GetId4(int largeId, int x, int y, int z)
{
Mapper mapper = new Mapper()
{
Short0 = (Int16)z,
Short1 = (Int16)y,
Short2 = (Int16)x,
Short3 = (Int16)largeId
};
return mapper.Combined;
}
private static Mapper _mapper = new Mapper();
public static long GetId5(int largeId, int x, int y, int z)
{
_mapper.Short0 = (Int16)z;
_mapper.Short1 = (Int16)y;
_mapper.Short2 = (Int16)x;
_mapper.Short3 = (Int16)largeId;
return _mapper.Combined;
}
[StructLayout(LayoutKind.Explicit)]
public struct Mapper2
{
[FieldOffset(0)] public Int64 Combined;
[FieldOffset(0)] public Int32 Integer0;
[FieldOffset(4)] public Int32 Integer1;
}
private static Mapper2 _mapper2 = new Mapper2();
public static long GetId6(int largeId, int x, int y, int z)
{
_mapper2.Integer0 = y << 16 | z; //dangerous because we aren't checking upper bits of z
_mapper2.Integer1 = largeId << 16 | x; //dangerous because we aren't checking upper bits of x
return _mapper2.Combined;
}
结果:
GetId1 = 2168ms
GetId2 = 1824ms
GetId3 = 1679ms
GetId4 = 2217ms
GetId5 = 2008ms
GetId6 = 1757ms
GetCoord1 = 785ms
GetCoord2 = 865ms
Routine1: 71776849217913036 binary: 11111111000000001010101000000000101110110000000011001100
Routine2: 71776849217913036 binary: 11111111000000001010101000000000101110110000000011001100
Routine3: 71776849217913036 binary: 11111111000000001010101000000000101110110000000011001100
Routine4: 71776849217913036 binary: 11111111000000001010101000000000101110110000000011001100
Routine5: 71776849217913036 binary: 11111111000000001010101000000000101110110000000011001100
Routine6: 71776849217913036 binary: 11111111000000001010101000000000101110110000000011001100
255, 170, 187, 204
255, 170, 187, 204
有没有更好/更快的方法将这4个整数编码成64位长整型?
(FYI… BitConverter类速度非常慢,且由于不可行而已被移除)
int64 Id64
的地址转换为short x[4]
,以便我可以复制它而不是移位。 或者只需使用memcpy。这可能比移位快或慢取决于情况。 - Dave S