什么是非常少量数据的最佳压缩库(3-4 kib?)

时间:2010-02-17 09:55:25

标签: networking lossless-compression quake

我正在开发一个游戏引擎,它是Quake 2的松散后裔,增加了一些像脚本效果的东西(允许服务器向客户端详细指定特殊效果,而不是只有有限数量的硬编码效果,客户端能够。)这是对网络效率的灵活性的折衷。

我遇到了一个有趣的障碍。请参阅,最大数据包大小为2800字节,每个客户端每帧只能有一个数据包。

以下是执行“火花”效果的脚本(可能对子弹撞击火花,电击等有用) http://pastebin.com/m7acdf519(如果您不理解它,请不要冒汗;这是我制作的自定义语法,与我提出的问题无关。)

我已尽一切可能缩小该脚本的大小。我甚至将变量名称缩减为单个字母。但结果恰好是405个字节。这意味着每帧最多可以容纳6个。我还想到了一些服务器端的更改,可以将其另外更改为12,并且协议更改可能会节省另外6个。虽然节省会因您使用的脚本而异。

然而,在那些387个字节中,我估计只有41个在效果的多次使用之间是唯一的。换句话说,这是压缩的主要候选者。

恰恰相反,R1Q2(具有扩展网络协议的向后兼容Quake 2引擎)具有Zlib压缩代码。我可以提起这段代码,或至少密切关注它作为参考。

但是Zlib一定是这里的最佳选择吗?我可以想到至少一种替代方案,LZMA,并且可能会有更多。

要求:

  1. 必须非常快(如果每秒运行超过100次,则必须具有非常小的性能。)
  2. 必须将尽可能多的数据填入2800字节
  3. 小元数据足迹
  4. 兼容GPL
  5. Zlib看起来不错,但有什么更好的吗?请记住,这些代码都没有被合并,因此有足够的实验空间。

    谢谢, -max

    编辑:感谢那些建议将脚本编译成字节码的人。我应该明白这一点 - 是的,我这样做。如果你愿意,你可以在我的网站上浏览相关的源代码,虽然它仍然没有“漂亮” 这是服务器端代码:
    Lua组件:http://meliaserlow.dyndns.tv:8000/alienarena/lua_source/lua/scriptedfx.lua
    C分量:http://meliaserlow.dyndns.tv:8000/alienarena/lua_source/game/g_scriptedfx.c
    对于我发布的特定示例脚本,这将获得一个低至405字节的1172字节源 - 仍然不够小。 (请记住,我希望将尽可能多的这些内容放入2800字节!)

    EDIT2:无法保证任何给定的数据包都会到达。每个数据包应该包含“世界状态”,而不依赖于先前数据包中传达的信息。通常,这些脚本将用于传达“眼睛糖果”。如果没有空间,它会从数据包中删除,这没什么大不了的。但如果有太多人掉线,那么事情在视觉上开始变得奇怪,这是不可取的。

6 个答案:

答案 0 :(得分:4)

LZO可能是一个很好的候选人。

答案 1 :(得分:2)

最终更新:这两个库似乎相当。 Zlib的压缩效率提高了约20%,而LZO的解码速度大约是其两倍,但两者的性能都非常小,几乎可以忽略不计。这是我的最终答案。感谢所有其他答案和评论!

UPDATE:在实施LZO压缩并且只看到明显更好的性能之后,显然我自己的代码应该归咎于性能损失(每个数据包可能大量增加脚本效果,因此我的效果“翻译”得到了更多的锻炼。)我想谦卑地为争抢责任而道歉,我希望没有难过的感情。我会做一些分析,然后我可能会得到一些对其他人更有用的数字。

原始邮件:

好的,我终于开始为此编写一些代码了。我从Zlib开始,这是我的第一个发现。

Zlib的压缩疯狂很棒。它可以将8.5 kib的数据包减少到750字节或更少,即使使用Z_BEST_SPEED(而不是Z_DEFAULT_COMPRESSION)压缩也是如此。压缩时间也相当不错。

但是,我不知道任何的解压缩速度甚至可能是这么糟糕。我没有实际数字,但至少每包需要1/8秒! (Core2Duo T550 @ 1.83 Ghz。)完全不能接受。

据我所知,与Zlib相比,LZMA是性能更差与更好压缩的权衡。由于Zlib的压缩已经过度杀伤并且其性能已经非常糟糕,LZMA目前看不到桌面。

如果LZO的减压时间与声称的一样好,那么这就是我将要使用的。我认为最终服务器仍然能够在极端情况下发送Zlib数据包,但客户端可以配置为忽略它们,这将是默认设置。

答案 2 :(得分:1)

zlib可能是一个很好的候选者 - 许可证非常好,工作速度很快,而且作者说它的开销非常小,而且开销是少量数据存在问题的原因。

答案 3 :(得分:1)

你应该看看OpenTNL并调整他们在那里使用的一些技术,比如网络字符串的概念

答案 4 :(得分:0)

我会倾向于使用当前浪费的每个字符的最高位,通过向左移动9个字节的组,您将适合8个字节。

你可以更进一步,将字符映射到一个小空间 - 你可以将它们降低到6位(即只有64个有效字符),例如,不允许使用大写字母并从每个字符中减去0x20(这样空间变为价值0)

您可以通过映射每个字符的频率进行更深入的操作,并进行霍夫曼类型压缩,以减少每个字符的平均数位。

我怀疑没有任何算法可以更好地保存数据,在一般情况下,因为在您进行了更改之后,消息中基本上没有冗余。

答案 5 :(得分:0)

如何发送脚本的二进制表示?

所以我在思考一个抽象语法树的行,每个过程都有一个标识符。

这意味着由于一次解析而导致客户端的性能提升,并且由于删除了方法名称而减小了大小。