用于服务器 - 客户端消息的快速文本解析器 - MMO

时间:2012-01-14 23:46:23

标签: c# performance message text-parsing mmo

应用

我正在制作一个MMO并遇到了一个问题。我构建的MMO服务器在UDP套接字上每隔约50毫秒快速并在本地向我的游戏客户端发送消息。以下是通过我当前的消息系统从服务器到客户端的消息示例:

  

计数= {2} =身体{[T = {} AGT ID = {42231} POS = {[50.40142117456183,146.3123192153775]}腐= {} 200.0,T = {} AGT ID = {4946} POS = { [65.83051652925558,495.25839757504866]}腐= {187.0}}

count={2}, 2 = number of objects
[,] = array of objects

我构建了一个简单的文本解析器,代码为:http://tinypaste.com/af3fb928

我使用的信息如下:

    int objects = int.Parse(UTL.Parser.DecodeMessage("count", message));
    string body = UTL.Parser.DecodeMessage("body", message);
    for (int i = 0; i < objects; i++)
    {
        string objectStr = UTL.Parser.DecodeMessage("[" + i + "]", body);
        // parse objecStr with UTL.Parser.DecodeMessage to extract pos & rot and apply to objects
    )

问题

当我有更多物体~60+时,性能会急剧下降。

问题

MMO或实时在线游戏中客户端和服务器之间打包和阅读邮件的标准方法是什么?

3 个答案:

答案 0 :(得分:2)

这里的二进制协议要快得多。以您传入的坐标为例。当您将它们作为字节传输时,它们将占用每个轴8个字节,而字符串表示使用2个字节每个字符(除非您以ASCII格式传输,但即使这样,二进制双精度也会更小)。

然后实际上把那个字符串变成一个数字是更多的工作;首先必须创建一个子字符串,以后会产生垃圾收集开销,必须解析这个数字并不快(但公平地说,你仍然可以解析每秒数十万的双打),因为.NET的{{1非常通用,必须适应很多不同的格式。如果你坚持使用文本,你可以通过编写自己的双解析器获得明显的速度,但就像我说的,如果消息解析是一个瓶颈,你应该使用二进制文件。将字节转换为双精度(带有一点double.Parse魔法,如果你正在运行服务器并且应该具有完全信任模式,这应该没问题)是复制8个字节的问题。

如果您的消息大多只是坐标等,我认为您可以通过创建自己的二进制格式获得很多收益。

答案 1 :(得分:1)

我会考虑使用像Thrift之类的RPC框架来为您解决问题。它将为您进行打包和解析,并通过二进制文件发送内容,以便更有效。

还有很多其他选择。 Here是一些比较。

答案 2 :(得分:1)

您的一个问题可能是不必要的字符串实例化。每次进行连接,拆分或获取子字符串时,都会在堆栈上创建新的字符串实例,这些实例将从原始字符串中复制,然后需要进行收集。

尝试更改代码以逐个字符地迭代字符串,并仅使用原始字符串解析数据。您应该只使用索引indexOf,甚至可能编写自己的int和float解析器,它们接受字符串偏移+长度以避免创建子字符串。我不确定这是否过度,但如果您有确凿的证据证明它运作缓慢,那么这不是“过早”的优化。

另外,您是否尝试过协议缓冲区?我相信他们的表现should be pretty good(只需编写一个小型控制台应用程序进行基准测试)。或者使用JSON,这是一种标准的简洁格式(但我不知道Json.NET是如何优化的)。在性能方面通常不应该击败硬编码的专用解析器,但考虑到未来的维护,我会先尝试其中一种协议。