热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

netty使用字典提升短文本的压缩效果

1问题术语:压缩率,compressionratio,压缩后的大小/压缩前的大小,越小说明压缩效果越好。在使用netty的JdkZlibEncoder进行压缩时,发现了一个问题:它

1 问题

  术语:压缩率,compression ratio,压缩后的大小/压缩前的大小,越小说明压缩效果越好。

  在使用netty的JdkZlibEncoder进行压缩时,发现了一个问题:它对于短文本(小于2K)的压缩效果很差,压缩率在80%-120%,文本越短,压缩效果越差,甚至可能比没压缩前更大。

  通过研究发现,使用字典可以改进压缩效果。以下详细介绍如何做。


2 提取字典

  我们要传输的文本类似于:

1
2
3
4
5

  提取字典的原则:将重复出现的字符串加入到字典。

  可以提取以下字典:

1 String[] dictiOnary= {
2 "",
3 "Event", "TRANSIENT", "attribute", "outer", "from", "trunk",
4 "callid", "id", "to", "ext"
5 };
6

 
3 测试用例

  使用EmbeddedChannel API来构建测试用例。EmbeddedChannel能够模拟入站和出站的数据流,对于测试ChannelHandler非常有用。

  JdkZlibEncoder的构造函数可以接受一个字典参数:

 

  下面是测试代码:

1 public class GzipTest {
2
3
4 private String xml = "" +
5 "" +
6 "" +
7 "" +
8 "
";
9
10 private String[] dictiOnary= {
11 "",
12 "Event", "TRANSIENT", "attribute", "outer", "from", "trunk",
13 "callid", "id", "to", "ext"
14 };
15
16
17 /**
18 * 不使用字典压缩
19 */
20 @Test
21 public void test1() {
22 EmbeddedChannel embeddedChannel = new EmbeddedChannel();
23 ChannelPipeline pipeline = embeddedChannel.pipeline();
24 //
25 pipeline.addLast("gzipDecoder", new JdkZlibDecoder());
26 pipeline.addLast("gzipEncoder", new JdkZlibEncoder(9));
27 pipeline.addLast("decoder", new StringDecoder());
28 pipeline.addLast("encoder", new StringEncoder());
29 //
30 System.out.println("*******不使用字典压缩*******");
31 int compressBefore = xml.getBytes(StandardCharsets.UTF_8).length;
32 System.out.printf("压缩前大小:%d \n", compressBefore);
33 // 模拟输出
34 embeddedChannel.writeOutbound(xml);
35 ByteBuf outboundBuf = embeddedChannel.readOutbound();
36 int compressAfter = outboundBuf.readableBytes();
37 System.out.printf("压缩后大小:%d, 压缩率:%d%% \n", compressAfter,
38 compressAfter * 100 / compressBefore);
39
40 }
41
42 /**
43 * 使用字典压缩
44 */
45 @Test
46 public void test2() {
47 EmbeddedChannel embeddedChannel = new EmbeddedChannel();
48 ChannelPipeline pipeline = embeddedChannel.pipeline();
49 // 字典
50 byte[] dictiOnaryBytes= String.join("", dictionary)
51 .getBytes(StandardCharsets.UTF_8);
52 //
53 pipeline.addLast("gzipDecoder", new JdkZlibDecoder(dictionaryBytes));
54 pipeline.addLast("gzipEncoder", new JdkZlibEncoder(9, dictionaryBytes));
55 pipeline.addLast("decoder", new StringDecoder());
56 pipeline.addLast("encoder", new StringEncoder());
57 //
58 System.out.println("*******使用字典压缩*******");
59 int compressBefore = xml.getBytes(StandardCharsets.UTF_8).length;
60 System.out.printf("压缩前大小:%d \n", compressBefore);
61 // 模拟输出
62 embeddedChannel.writeOutbound(xml);
63 ByteBuf outboundBuf = embeddedChannel.readOutbound();
64 int compressAfter = outboundBuf.readableBytes();
65 System.out.printf("压缩后大小:%d, 压缩率:%d%% \n", compressAfter,
66 compressAfter * 100 / compressBefore);
67 }
68
69
70 }

 

输出:

*******不使用字典压缩*******
压缩前大小:173
压缩后大小:150, 压缩率:86%
*******使用字典压缩*******
压缩前大小:173
压缩后大小:95, 压缩率:54%

  从输出可以看到,压缩率由86%提升至了54%。


4 进一步

  如果觉得手工提取字典效率太低,还可以试一下zstd。zstd是由facebook提供的一个压缩库,它提供了自动提取字典的工具。命令如下:

 zstd --train ./dictionary/* -o ./dict.bin
5 参考资料

zstd github

文本压缩算法的对比和选择



推荐阅读
  • 电话号码的字母组合解题思路和代码示例
    本文介绍了力扣题目《电话号码的字母组合》的解题思路和代码示例。通过使用哈希表和递归求解的方法,可以将给定的电话号码转换为对应的字母组合。详细的解题思路和代码示例可以帮助读者更好地理解和实现该题目。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 本文介绍了一种划分和计数油田地块的方法。根据给定的条件,通过遍历和DFS算法,将符合条件的地块标记为不符合条件的地块,并进行计数。同时,还介绍了如何判断点是否在给定范围内的方法。 ... [详细]
  • JVM 学习总结(三)——对象存活判定算法的两种实现
    本文介绍了垃圾收集器在回收堆内存前确定对象存活的两种算法:引用计数算法和可达性分析算法。引用计数算法通过计数器判定对象是否存活,虽然简单高效,但无法解决循环引用的问题;可达性分析算法通过判断对象是否可达来确定存活对象,是主流的Java虚拟机内存管理算法。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
author-avatar
NAVETEX
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有