我正在嘗試爲正在編寫的遊戲編寫通用套接字服務器。我知道我可以很好地使用像SmartFox和Photon這樣已經構建好的服務器,但是我不想經歷爲了學習目的而自己創建一個服務器的痛苦。改進二進制轉換並返回C#
我想出了一個BSON啓發式協議來將基本數據類型,它們的數組和一個特殊的GSObject轉換爲二進制,並以一種方式安排它們,以便它可以一起放回到對象形式客戶端。在覈心,轉換方法利用.Net BitConverter類將基本數據類型轉換爲二進制。無論如何,問題是性能,如果我循環5萬次,並將我的GSObject轉換爲二進制,每次大約需要5500毫秒(結果字節[]僅爲每轉換192字節)。我認爲這對於一個每秒發送5-10個位置更新並有1000個併發用戶的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/),但任何分析器都可以。 – 2012-04-02 22:30:35
@ChrisShain不,我沒有,我真的不知道我可以做到這一點,但我會考慮這一點,謝謝你的建議。 – 2012-04-02 22:35:19
這篇文章太遠了,太長了。請重點關注問題的相關部分,將代碼重新降至10%。 – Gray 2012-04-02 22:40:55