C# 改进C语言中的二进制和二进制转换#
我正在尝试为我正在开发的游戏编写一个通用套接字服务器。我知道我可以很好地使用像SmartFox和Photon这样已经构建好的服务器,但我不想为了学习而自己创建一个服务器 我提出了一个受BSON启发的协议,将基本数据类型、它们的数组和一个特殊的GSObject转换为二进制,并以某种方式对它们进行排列,以便在客户端将它们重新组合成对象形式。在核心,转换方法利用.Net BitConverter类将基本数据类型转换为二进制。不管怎么说,问题在于性能,如果我循环50000次,每次大约5500ms(每次转换得到的字节[]仅为192字节)时,将我的GSObject转换为二进制。我认为这对于一个每秒发送5-10个位置更新,同时有1000个用户的MMO来说太慢了。是的,我知道一款游戏不太可能同时拥有1000名用户,但正如我之前所说的,这对我来说应该是一个学习过程,我想不遗余力地构建一款可扩展的游戏,能够处理至少几千名用户 所以,是的,如果有人知道其他转换技术,或者看到我的性能下降的地方,我将非常感谢您的帮助 GSBitConverter.cs 这是主转换类,它向主数据类型添加扩展方法以转换为二进制格式。它使用BitConverter类来转换基类型。我只展示了转换integer和integer数组的代码,但该方法的其余部分基本上是这两个数组的副本,它们只是重载了类型C# 改进C语言中的二进制和二进制转换#,c#,binary-data,bitconverter,C#,Binary Data,Bitconverter,我正在尝试为我正在开发的游戏编写一个通用套接字服务器。我知道我可以很好地使用像SmartFox和Photon这样已经构建好的服务器,但我不想为了学习而自己创建一个服务器 我提出了一个受BSON启发的协议,将基本数据类型、它们的数组和一个特殊的GSObject转换为二进制,并以某种方式对它们进行排列,以便在客户端将它们重新组合成对象形式。在核心,转换方法利用.Net BitConverter类将基本数据类型转换为二进制。不管怎么说,问题在于性能,如果我循环50000次,每次大约5500ms(每次转
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);
}
公共静态类GSBitConverter
{
公共静态字节[]ToGSBinary(此短值)
{
返回BitConverter.GetBytes(值);
}
公共静态字节[]ToGSBinary(此IEnumerable值)
{
列表字节=新列表();
short length=(short)value.Count();
bytes.AddRange(length.ToGSBinary());
for(int i=0;i
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");
}
类程序
{
静态void Main(字符串[]参数)
{
GSObject obj=新的GSObject();
对象附件(“smallInt”,15);
附件(“medInt”,120700);
附件(“bigInt”,10900800700);
对象附件(doubleVal,Math.PI);
对象AttachStringaray(“木偶名称”,新字符串[]{“Kermit”,“Fozzy”,“Piggy”,“Animal”,“Gonzo”});
GSObject apple=新的GSObject();
苹果。附件字符串(“名称”、“苹果”);
苹果。附加字符串(“颜色”、“红色”);
苹果。AttachBool(“inStock”,真);
苹果公司(apple.AttachFloat)(“价格”(price),(float)1.5);
GSObject lemon=新的GSObject();
苹果。附加字符串(“名称”、“柠檬”);
苹果。附加字符串(“颜色”、“黄色”);
苹果。AttachBool(“inStock”,假);
苹果公司(apple.AttachFloat)(价格)(浮动)0.8);
GSObject apricat=新的GSObject();
苹果。附件字符串(“名称”、“Apricoat”);
苹果。附加字符串(“颜色”、“橙色”);
苹果。AttachBool(“inStock”,真);
苹果公司(apple.AttachFloat)(“价格”(price),(float)1.9);
GSObject kiwi=新的GSObject();
苹果。附件(“名称”、“猕猴桃”);
苹果。附加字符串(“颜色”、“绿色”);
苹果。AttachBool(“inStock”,真);
苹果公司(apple.AttachFloat)(“价格”(price),(float)2.3);
GSArray水果=新的GSArray();
水果。苹果;
水果。添加物体(柠檬);
果实。添加物体(杏壳);
水果。添加对象(猕猴桃);
附件(“水果”,水果);
秒表w1=Stopwatch.StartNew();
对于(int i=0;i<50000;i++)
{
字节[]b=obj.ToGSBinary();
}
w1.停止();
Console.WriteLine(BitConverter.IsLittleEndian?“小Endian”:“大Endian”);
控制台写入线(w1.elapsedmillyses+“ms”);
}
这是我在上面的代码中使用的其他一些类的代码,其中大部分是重复的
1)ElementAt非常昂贵。使用foreach(var v值)
而不是for(int i=0;i
2) ToGsBinary方法非常昂贵,因为它们经常复制数组。
使用签名void WriteToGsBinary(Stream-Stream)
代替byte[]ToGsBinary()
3) 为数组添加重载:
void WriteToGsBinary(Stream-Stream,byte[]值)
,void WriteToGsBinary(Stream-Stream,short[]值)
,等等我的第一个预感是,如果没有太多问题,你的很多时间都在不断地重新创建数组和列表
我倾向于使用基于流的方法,而不是不断尝试创建数组。也就是说,让所有的GSBinary方法都接受一个流,然后写入它,而不是创建自己的数组,如果你想要的话