protobuf compress - landon30/Bulls GitHub Wiki

proto消息过长

  • BullsWeakNetFilter#filterWrite

    GC_SUDDENCRIME_ATTACK_RESULT = 70012 击杀结果包括战报(十几个Round) netMessage.getData().length = 52826 (short) data.length = -12710 Short.MAX_VALUE = 32767

  • 即包括战报的数据长度大约50k,超出了长度字段(short)
    • 之前的测试是没有加snappy压缩,可以先测试一下用snappy压缩之后战报数据大小
      • 52732(压缩前) 5585(压缩后)
      • snappy的压缩比还是很不错
    • 保险起见,一定要将长度字段的short(16bit)要改为int(32bit)
  • 测试protobuf vs snappy
    • 从测试输出结果看
    • String类型, pb压缩不明显
    • json重复key多,snappy压缩明显
  • 总结1
    • Protocol buffers are an efficient binary serialization format, not a compressor
    • strings do not become any smaller as their payload remains the same
    • If you need to reduce the size, you could either gzip the data or use an application-level dictionary to substitute large strings with something smaller
    • 即pb和snappy解决的是不同的问题,一起用比较好
  • 总结2:
    • A
      • 我们以前是消息是否压缩是开发人员控制,消息协议头里有个标志本消息是否进行了压缩处理。因为压缩还是要消耗不少性能
      • 登录、战斗、同屏,消息比较大,进行压缩。其它就不压缩追求性能
      • 还做过一种,是框架底层发现消息太大就自动压缩
      • 现在的项目对性能要求不高,瓶颈不会在压缩上,还好
    • B
      • 我们现在是支持不压缩的,但是不建议不压缩,大多数情况下,压缩会有效果的,不管是不是PB,越压越大的情况少
      • 业务里的消息大小,是控制不住的
      • 这就是看主程的控制粒度了, 如果哪个新来的开发不知道这些细节,哪天写个大数据接口出来,没压缩,那就挂了。snappy 经过了验证,性能不会有太大问题的,建议统一处理,上层就不需要区分了
      • 大多数情况下,不用太过于追求极致的细节性能优化,做的傻一些,灵活度低一些,稳定是第一优先级。
      • 统一压缩
      • 网络层自始至终是不允许自己修改的
      • landon:这个确实比较底层 如果擅自修改 引起其他不必要的问题 就不好了;MinaTypicalNetIO这个部分确实是历史原因,不过无论是这个mina或者还是后续的其他网络库 网络层其实也不建议修改;除非有特别需求 但通常这个需求可能是通用的
  • 总结3:
    • landon:之前一直觉得用protobuf就不用压缩了,但其实还是没有深入理解。在战报传输这种大量的重复字符串的情况下,protobuf结合压缩如snappy是非常好的解决方案
    @Test
    public void testProtobufCompresss() {
	    // 这里省略输入战报字符串,太长
        String result = "{\"battleResult\":-1....}";
		
		BattleResultReplayMsg.Builder builder = BattleResultReplayMsg.newBuilder();
        builder.setReplayResult(result);
        byte[] bytes = builder.build().toByteArray();
		
		// protobuf.byte:43539
        System.out.println("protobuf.byte:" + bytes.length);

        ICompressAlgorithm algorithm = CompressAlgorithmFactory
                .create(DataCompressType.SNAPPY.getType());
        byte[] compressedData = algorithm.compress(bytes);
		
		// compressedData.byte:4872
        System.out.println("compressedData.byte:" + compressedData.length);
    }