Идея: быть в состоянии взять байты любой структуры, отправить эти байты через 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;
}
Помогите, пожалуйста,спасибо.
Редактировать:
Ну, одна из основных проблем заключается в том, что я получаю дескриптор временной копии, созданной при передаче значения структуры.
Edit2:
Изменение "T r = new T ();"на "объект г = новый T ();"и «return r» для «return (T) r» блокирует и распаковывает структуру и тем временем делает ее ссылкой, поэтому указатель фактически указывает на нее.
Однако, это медленно.Я получаю 13 500 - 14 500 операций записи / чтения в секунду.
Edit3:
OTOH, сериализация / десериализация Vector3 через BinaryFormatter получает около 750 операций записи / чтения в секунду.Так что Lot быстрее, чем я использовал.:)
Edit4:
Индивидуальная отправка поплавков получила 8 400 RW / сек.Внезапно я чувствую себя намного лучше об этом.:)
Редактировать5:
Проверено закрепление и освобождение выделения GCHandle;28 000 000 операций в секунду (по сравнению с 1 000 000 000 Int32 / int add + assign / second. Таким образом, по сравнению с целыми числами, это в 35 раз медленнее. Однако это все еще достаточно быстро).Обратите внимание, что вы, кажется, не в состоянии закрепить классы, даже если GCHandle прекрасно работает с автоматически упакованными структурами (GCHandle принимает значения типа «объект»).
Теперь, если ребята из 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 операций в секунду:
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