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

本文关键字:文本 -MMO 服务器 客户端 消息 用于 | 更新日期: 2023-09-27 18:20:31

应用程序

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

计数={2}body={={agt}id={42231}pos={[504014217456183146.3123192153775]}rot={200.0},t={agt}id={4946}pos={[65.8305165529255854854866]}rot={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或实时在线游戏中,客户端和服务器之间打包和读取消息的标准方法是什么?

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

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

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

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

问题之一可能是不必要的字符串实例化。任何时候进行串联、拆分或获取子字符串时,都会在堆栈上创建新的字符串实例,这些实例是从原始字符串复制的,之后需要收集。

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

另外,你试过协议缓冲区吗?我相信他们的性能应该很好(只需为基准测试编写一个小型控制台应用程序)。或者使用JSON,这是一种标准的简洁格式(但我不知道JSON.NET是如何优化的)。在性能方面,通常没有什么能比得上硬编码的专用解析器,但考虑到未来的维护,我会先尝试其中一种协议。

我会考虑使用像Thrift这样的RPC框架来为您做提升。它将为您进行打包和解析,并以二进制形式通过网络发送内容,从而提高效率。

还有很多其他的选择。以下是一些比较。