내가 작업중인 게임을위한 범용 소켓 서버를 작성하려고합니다. SmartFox 및 Photon과 같은 이미 구축 된 서버를 사용할 수는 있지만, 학습 목적으로 직접 만드는 것의 어려움을 겪지 않을 것입니다.이진 변환을 개선하고 C#으로 돌아 가기
BSON에서 영감을받은 프로토콜을 사용하여 기본 데이터 유형, 해당 배열 및 특수 GSObject를 바이너리로 변환 한 다음이를 다시 배열하여 객체 형식으로 다시 배치 할 수 있도록했습니다. 클라이언트 끝. 핵심에서 변환 방법은 .Net BitConverter 클래스를 사용하여 기본 데이터 형식을 이진 형식으로 변환합니다. 어쨌든, 문제는 성능입니다. 반복 횟수를 50,000 회 돌리고 내 GSObject를 5500ms가 될 때마다 바이너리로 변환합니다. 결과 바이트 []는 변환 당 192 바이트입니다. 나는 이것이 1000 명의 동시 사용자로 초당 5-10 개의 위치 업데이트를 보내는 MMO에서 너무 느릴 것이라고 생각합니다. 예, 게임에 1000 명의 사용자가 동시에있을 가능성은 거의 없습니다. 그러나 이전에 내가 말했던 것처럼이 과정은 저를위한 학습 과정으로되어 있다고 말했듯이 저리 비켜서 잘 확장되는 무언가를 만들고 싶습니다. 최소한 수천 명의 사용자를 처리 할 수 있습니다.
누군가 다른 변환 기술을 알고 있거나 내가 성능을 잃어버린 곳을 본다면 도움을 주시면 감사하겠습니다.
GSBitConverter.cs
이 메인 변환 클래스, 그것은 주요 데이터 유형에 대한 확장 방법은 바이너리 포맷으로 변환하는 추가합니다. BitConverter 클래스를 사용하여 기본 형식을 변환합니다. 정수 및 정수 배열을 변환하는 코드 만 표시했지만 나머지 메서드는 거의이 두 가지의 복제본이므로 형식이 너무 많이 오버로드됩니다.
public static class GSBitConverter
{
public static byte[] ToGSBinary(this short value)
{
return BitConverter.GetBytes(value);
}
public static byte[] ToGSBinary(this IEnumerable<short> value)
{
List<byte> bytes = new List<byte>();
short length = (short)value.Count();
bytes.AddRange(length.ToGSBinary());
for (int i = 0; i < length; i++)
bytes.AddRange(value.ElementAt(i).ToGSBinary());
return bytes.ToArray();
}
public static byte[] ToGSBinary(this bool value);
public static byte[] ToGSBinary(this IEnumerable<bool> value);
public static byte[] ToGSBinary(this IEnumerable<byte> value);
public static byte[] ToGSBinary(this int value);
public static byte[] ToGSBinary(this IEnumerable<int> value);
public static byte[] ToGSBinary(this long value);
public static byte[] ToGSBinary(this IEnumerable<long> value);
public static byte[] ToGSBinary(this float value);
public static byte[] ToGSBinary(this IEnumerable<float> value);
public static byte[] ToGSBinary(this double value);
public static byte[] ToGSBinary(this IEnumerable<double> value);
public static byte[] ToGSBinary(this string value);
public static byte[] ToGSBinary(this IEnumerable<string> value);
public static string GetHexDump(this IEnumerable<byte> value);
}
Program.cs 는 여기에 내가 루프에서 바이너리로 전환하고있어 객체입니다.
class Program
{
static void Main(string[] args)
{
GSObject obj = new GSObject();
obj.AttachShort("smallInt", 15);
obj.AttachInt("medInt", 120700);
obj.AttachLong("bigInt", 10900800700);
obj.AttachDouble("doubleVal", Math.PI);
obj.AttachStringArray("muppetNames", new string[] { "Kermit", "Fozzy", "Piggy", "Animal", "Gonzo" });
GSObject apple = new GSObject();
apple.AttachString("name", "Apple");
apple.AttachString("color", "red");
apple.AttachBool("inStock", true);
apple.AttachFloat("price", (float)1.5);
GSObject lemon = new GSObject();
apple.AttachString("name", "Lemon");
apple.AttachString("color", "yellow");
apple.AttachBool("inStock", false);
apple.AttachFloat("price", (float)0.8);
GSObject apricoat = new GSObject();
apple.AttachString("name", "Apricoat");
apple.AttachString("color", "orange");
apple.AttachBool("inStock", true);
apple.AttachFloat("price", (float)1.9);
GSObject kiwi = new GSObject();
apple.AttachString("name", "Kiwi");
apple.AttachString("color", "green");
apple.AttachBool("inStock", true);
apple.AttachFloat("price", (float)2.3);
GSArray fruits = new GSArray();
fruits.AddGSObject(apple);
fruits.AddGSObject(lemon);
fruits.AddGSObject(apricoat);
fruits.AddGSObject(kiwi);
obj.AttachGSArray("fruits", fruits);
Stopwatch w1 = Stopwatch.StartNew();
for (int i = 0; i < 50000; i++)
{
byte[] b = obj.ToGSBinary();
}
w1.Stop();
Console.WriteLine(BitConverter.IsLittleEndian ? "Little Endian" : "Big Endian");
Console.WriteLine(w1.ElapsedMilliseconds + "ms");
}
위의 코드에서 사용되는 다른 클래스의 코드는 다음과 같습니다. 대부분은 반복적입니다.
시간을 어디에서 사용했는지 프로필러에서 확인해 보았습니까? 필자는 개인적으로 dotTrace (http://www.jetbrains.com/profiler/)를 선호하지만 프로파일 작성기는 그렇게 할 것입니다. –
@ChrisShain 아니, 나는 그것을 할 수 있다는 것을 실제로 알지 못했다. 그러나 나는 그것을 조사 할 것이다. 제안에 감사한다. –
이 게시물은 멀리, 너무 오래 됐어. 문제의 관련 부분을 집중하여 코드를 다시 10 %로 줄이십시오. – Gray