netty 使用字典提升短文本的压缩效果
1 问题
术语:压缩率,compression ratio,压缩后的大小/压缩前的大小,越小说明压缩效果越好。
在使用netty的JdkZlibEncoder进行压缩时,发现了一个问题:它对于短文本(小于2K)的压缩效果很差,压缩率在80%-120%,文本越短,压缩效果越差,甚至可能比没压缩前更大。
通过研究发现,使用字典可以改进压缩效果。以下详细介绍如何做。
2 提取字典
我们要传输的文本类似于:
<?xml version="1.0" encoding="utf-8" ?>
<Event attribute="TRANSIENT">
<outer id="" from="" to="" trunk="" callid=""/>
<ext id=""/>
</Event>
提取字典的原则:将重复出现的字符串加入到字典。
可以提取以下字典:
String[] dictionary = {
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>",
"Event", "TRANSIENT", "attribute", "outer", "from", "trunk",
"callid", "id", "to", "ext"
};
3 测试用例
使用EmbeddedChannel API来构建测试用例。EmbeddedChannel能够模拟入站和出站的数据流,对于测试ChannelHandler非常有用。
JdkZlibEncoder的构造函数可以接受一个字典参数:
下面是测试代码:
public class GzipTest { private String xml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" +
"<Event attribute=\"TRANSIENT\">" +
"<outer id=\"11\" from=\"1005\" to=\"915880056212\" trunk=\"83057387\" callid=\"24587\" />" +
"<ext id=\"1005\" />" +
"</Event>"; private String[] dictionary = {
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>",
"Event", "TRANSIENT", "attribute", "outer", "from", "trunk",
"callid", "id", "to", "ext"
}; /**
* 不使用字典压缩
*/
@Test
public void test1() {
EmbeddedChannel embeddedChannel = new EmbeddedChannel();
ChannelPipeline pipeline = embeddedChannel.pipeline();
//
pipeline.addLast("gzipDecoder", new JdkZlibDecoder());
pipeline.addLast("gzipEncoder", new JdkZlibEncoder(9));
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
//
System.out.println("*******不使用字典压缩*******");
int compressBefore = xml.getBytes(StandardCharsets.UTF_8).length;
System.out.printf("压缩前大小:%d \n", compressBefore);
// 模拟输出
embeddedChannel.writeOutbound(xml);
ByteBuf outboundBuf = embeddedChannel.readOutbound();
int compressAfter = outboundBuf.readableBytes();
System.out.printf("压缩后大小:%d, 压缩率:%d%% \n", compressAfter,
compressAfter * 100 / compressBefore); } /**
* 使用字典压缩
*/
@Test
public void test2() {
EmbeddedChannel embeddedChannel = new EmbeddedChannel();
ChannelPipeline pipeline = embeddedChannel.pipeline();
// 字典
byte[] dictionaryBytes = String.join("", dictionary)
.getBytes(StandardCharsets.UTF_8);
//
pipeline.addLast("gzipDecoder", new JdkZlibDecoder(dictionaryBytes));
pipeline.addLast("gzipEncoder", new JdkZlibEncoder(9, dictionaryBytes));
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
//
System.out.println("*******使用字典压缩*******");
int compressBefore = xml.getBytes(StandardCharsets.UTF_8).length;
System.out.printf("压缩前大小:%d \n", compressBefore);
// 模拟输出
embeddedChannel.writeOutbound(xml);
ByteBuf outboundBuf = embeddedChannel.readOutbound();
int compressAfter = outboundBuf.readableBytes();
System.out.printf("压缩后大小:%d, 压缩率:%d%% \n", compressAfter,
compressAfter * 100 / compressBefore);
} }
输出:
*******不使用字典压缩******* 压缩前大小:173 压缩后大小:150, 压缩率:86% *******使用字典压缩******* 压缩前大小:173 压缩后大小:95, 压缩率:54%
从输出可以看到,压缩率由86%提升至了54%。
4 进一步
如果觉得手工提取字典效率太低,还可以试一下zstd。zstd是由facebook提供的一个压缩库,它提供了自动提取字典的工具。命令如下:
zstd --train ./dictionary/* -o ./dict.bin
5 参考资料
netty 使用字典提升短文本的压缩效果的更多相关文章
- redis底层数据结构--简单动态字符串 链表 字典 跳跃表 整数集合 压缩列表
1.动态字符串 redis中使用c语言的字符床存储字面量,默认字符串存储采用自己构建的简单动态字符串SDS(symple dynamic string) redis包含字符串的键值对都是用SDS实现的 ...
- 【redis】redis底层数据结构原理--简单动态字符串 链表 字典 跳跃表 整数集合 压缩列表等
redis有五种数据类型string.list.hash.set.zset(字符串.哈希.列表.集合.有序集合)并且自实现了简单动态字符串.双端链表.字典.压缩列表.整数集合.跳跃表等数据结构.red ...
- APK瘦身记,如何实现高达53%的压缩效果
作者:非戈@阿里移动安全 1.我是怎么思考这件事情的 APK是Android系统安装包的文件格式,关于这个话题其实是一个老生常谈的题目,不论是公司内部,还是外部网络,前人前辈已经总结出很多方法和规律. ...
- APK瘦身记,怎样实现高达53%的压缩效果
作者:非戈@阿里移动安全,很多其它技术干货.请訪问阿里聚安全博客 1.我是怎么思考这件事情的 APK是Android系统安装包的文件格式.关于这个话题事实上是一个老生常谈的题目.不论是公司内部.还是外 ...
- nginx_gzip压缩提升网站的传输速度
gzip on; gzip_min_length 1k; gzip_buffers 16k; #gzip_http_version 1.0; gzip_comp_level ; gzip_types ...
- Netty 系列之 Netty 高性能之道
1. 背景 1.1. 惊人的性能数据 最近一个圈内朋友通过私信告诉我,通过使用 Netty4 + Thrift 压缩二进制编解码技术,他们实现了 10 W TPS(1 K 的复杂 POJO 对象)的跨 ...
- Netty系列之Netty高性能之道
转载自http://www.infoq.com/cn/articles/netty-high-performance 1. 背景 1.1. 惊人的性能数据 最近一个圈内朋友通过私信告诉我,通过使用Ne ...
- Netty高性能之道
1. 背景 1.1. 惊人的性能数据 最近一个圈内朋友告诉我,通过使用Netty4 + Thrift压缩二进制编解码技术,他们实现了10W TPS(1K的复杂POJO对象)的跨节点远程服务调用.相比于 ...
- 转:Netty系列之Netty高性能之道
1. 背景 1.1. 惊人的性能数据 最近一个圈内朋友通过私信告诉我,通过使用Netty4 + Thrift压缩二进制编解码技术,他们实现了10W TPS(1K的复杂POJO对象)的跨节点远程服务调用 ...
随机推荐
- 且谈 Apache Spark 的 API 三剑客:RDD、DataFrame 和 Dataset
作者:Jules S. Damji 译者:足下 本文翻译自 A Tale of Three Apache Spark APIs: RDDs, DataFrames, and Datasets ,翻译已 ...
- Docker入门(1):概述
1.摘要 在这篇文章中,我将介绍一下为什么需要虚拟化的环境. 然后我将介绍耳熟能详的虚拟化技术:虚拟机,并大致的介绍一下虚拟机的原理,希望能够让你知道虚拟机的优劣. 在之后,针对虚拟机存在的问题,引出 ...
- jquery入门(3)
4.jQuery中的事件绑定 4.1.事件绑定 on方法绑定 $('#box').on('click',function(){ alert(1); }) 直接绑定 $("#box" ...
- 001_Linux常用命令之ls命令
1. 认识Linux系统目录结构 /bin 可执行文件所在目录 /media 挂载设备媒体,u盘,光驱等 /mnt 该目录主要是为了让用户挂在别的文件系统(挂在自己的u盘) /usr unix sys ...
- C# 做的Windows 应用程序 服务
运行服务: ,cmd下进入目录 cd C:\Windows\Microsoft.NET\Framework\v4.0.30319\ ,安装服务 installutil F:\中原集团\天津CCHR\t ...
- 利用 Nginx 实现限流
在当下互联网高并发时代中,项目往往会遇到需要限制客户端连接的需求.我们熟知的 Nginx 就提供了有这样的功能,可以简单的实现对客户端请求频率,并发连接和传输速度的限制…. Nginx 限流 Ngin ...
- scala数据结构(一)
一.概述 1,特点 )Scala同时支持不可变集合和可变集合 )两个主要的包: 不可变集合:scala.collection.immutable 可变集合: scala.collection.muta ...
- CentOS7下安装Docker《超详细新手教程》
1.使用 root 权限登录 Centos.确保 yum 包更新到最新. sudo yum update 2.卸载旧版本(如果安装过旧版本的话) sudo yum remove docker dock ...
- UiAutomator源码学习(2)-- UiAutomationBridge
从上一章对UiDevice的学习,可以看出几乎所有的操作都离不开 UiAutomationBridge.重新看一下UIDevice的构造方法: private UiDevice(Instrumenta ...
- vue 仿掘金评论列表
先来个最终效果 代码: template代码: <template> <div class="main"> <div class="titl ...