这个想法:能够获取任何结构的字节,通过TcpClient(或通过我的客户端包装器)发送这些字节,然后让接收客户端加载这些字节并使用指针将它们“绘制”到新结构上
问题:它完全将字节读入缓冲区;它完美地读取另一端的字节数组。然而,“油漆”操作失败了。我写了一个新的Vector3(1F,2F,3F);我读了一个Vector3(0F,0F,0F)......显然,不理想。
不幸的是,我没有看到错误 - 如果它以一种方式工作,它应该反过来 - 并且值正在被填充。
写/读功能如下:
public static unsafe void Write<T>(Client client, T value) where T : struct
{
int n = System.Runtime.InteropServices.Marshal.SizeOf(value);
byte[] buffer = new byte[n];
{
var handle = System.Runtime.InteropServices.GCHandle.Alloc(value, System.Runtime.InteropServices.GCHandleType.Pinned);
void* ptr = handle.AddrOfPinnedObject().ToPointer();
byte* bptr = (byte*)ptr;
for (int t = 0; t < n; ++t)
{
buffer[t] = *(bptr + t);
}
handle.Free();
}
client.Writer.Write(buffer);
}
换行
public static unsafe T Read<T>(Client client) where T : struct
{
T r = new T();
int n = System.Runtime.InteropServices.Marshal.SizeOf(r);
{
byte[] buffer = client.Reader.ReadBytes(n);
var handle = System.Runtime.InteropServices.GCHandle.Alloc(r, System.Runtime.InteropServices.GCHandleType.Pinned);
void* ptr = handle.AddrOfPinnedObject().ToPointer();
byte* bptr = (byte*)ptr;
for (int t = 0; t < n; ++t)
{
*(bptr + t) = buffer[t];
}
handle.Free();
}
return r;
}
请帮助,谢谢。
编辑:
好吧,一个主要问题是我得到了传递struct值时创建的临时副本的句柄。
EDIT2:
更改“T r = new T();” to“object r = new T();”并且“返回r”到“return(T)r”框并取消框结构,同时使它成为引用,所以指针实际指向它。
然而,它很慢。我每秒得到13,500 - 14,500次写入/读取。
EDIT3:
OTOH,通过BinaryFormatter序列化/反序列化Vector3每秒可获得大约750次写入/读取。所以 Lot 比我使用的更快。 :)
Edit4:
单独发送花车的速度为8,400 RW /秒。突然之间,我对此感觉好多了。 :)
Edit5:
经过测试的GCHandle分配固定和释放;每秒28,000,000 ops(相比于大约1,000,000,000 Int32 / int add + assign / second。因此与整数相比,它慢了35倍。但是,这仍然相当快)。请注意,即使GCHandle自动装箱结构正常(GCHandle接受“object”类型的值),您似乎也无法固定类。
现在,如果C#人员将约束更新到指针分配识别出“T”是结构的点,我可以直接指向一个指针,这是......,非常快。
接下来:可能使用单独的线程测试写入/读取。 :)看看GCHandle实际影响发送/接收延迟的程度。
事实证明:
Edit6:
double start = Timer.Elapsed.TotalSeconds;
for (t = 0; t < count; ++t)
{
Vector3 from = new Vector3(1F, 2F, 3F);
// Vector3* ptr = &test;
// Vector3* ptr2 = &from;
int n = sizeof(Vector3);
if (n / 4 * 4 != n)
{
// This gets 9,000,000 ops/second;
byte* bptr1 = (byte*)&test;
byte* bptr2 = (byte*)&from;
// int n = 12;
for (int t2 = 0; t2 < n; ++t2)
{
*(bptr1 + t2) = *(bptr2 + t2);
}
}
else
{
// This speedup gets 24,000,000 ops/second.
int n2 = n / 4;
int* iptr1 = (int*)&test;
int* iptr2 = (int*)&from;
// int n = 12;
for (int t2 = 0; t2 < n2; ++t2)
{
*(iptr1 + t2) = *(iptr2 + t2);
}
}
}
所以,总的来说,我认为GCHandle并没有真正放慢速度。 (那些认为这是将一个Vector3分配给另一个的慢速方法的人,请记住,目的是将结构序列化为byte []缓冲区以通过网络发送。而且,虽然这不是我们在这里做的,但它用第一种方法很容易做到。)
Edit7:
以下获得6,900,000 ops /秒:
for (t = 0; t < count; ++t)
{
Vector3 from = new Vector3(1F, 2F, 3F);
int n = sizeof(Vector3);
byte* bptr2 = (byte*)&from;
byte[] buffer = new byte[n];
for (int t2 = 0; t2 < n; ++t2)
{
buffer[t2] = *(bptr2 + t2);
}
}
...帮助!我有IntruigingPuzzlitus! :d