C# 改进C语言中的二进制和二进制转换#

C# 改进C语言中的二进制和二进制转换#,c#,binary-data,bitconverter,C#,Binary Data,Bitconverter,我正在尝试为我正在开发的游戏编写一个通用套接字服务器。我知道我可以很好地使用像SmartFox和Photon这样已经构建好的服务器,但我不想为了学习而自己创建一个服务器 我提出了一个受BSON启发的协议,将基本数据类型、它们的数组和一个特殊的GSObject转换为二进制,并以某种方式对它们进行排列,以便在客户端将它们重新组合成对象形式。在核心,转换方法利用.Net BitConverter类将基本数据类型转换为二进制。不管怎么说,问题在于性能,如果我循环50000次,每次大约5500ms(每次转

我正在尝试为我正在开发的游戏编写一个通用套接字服务器。我知道我可以很好地使用像SmartFox和Photon这样已经构建好的服务器,但我不想为了学习而自己创建一个服务器

我提出了一个受BSON启发的协议,将基本数据类型、它们的数组和一个特殊的GSObject转换为二进制,并以某种方式对它们进行排列,以便在客户端将它们重新组合成对象形式。在核心,转换方法利用.Net BitConverter类将基本数据类型转换为二进制。不管怎么说,问题在于性能,如果我循环50000次,每次大约5500ms(每次转换得到的字节[]仅为192字节)时,将我的GSObject转换为二进制。我认为这对于一个每秒发送5-10个位置更新,同时有1000个用户的MMO来说太慢了。是的,我知道一款游戏不太可能同时拥有1000名用户,但正如我之前所说的,这对我来说应该是一个学习过程,我想不遗余力地构建一款可扩展的游戏,能够处理至少几千名用户

所以,是的,如果有人知道其他转换技术,或者看到我的性能下降的地方,我将非常感谢您的帮助

GSBitConverter.cs

这是主转换类,它向主数据类型添加扩展方法以转换为二进制格式。它使用BitConverter类来转换基类型。我只展示了转换integer和integer数组的代码,但该方法的其余部分基本上是这两个数组的副本,它们只是重载了类型

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方法都接受一个流,然后写入它,而不是创建自己的数组,如果你想要的话