使用jmh框架进行benchmark测试
性能问题
最近在跑flink社区1.15版本使用json_value函数时,发现其性能很差,通过jstack查看堆栈经常在执行以下堆栈
可以看到这里的逻辑是在等锁,查看jsonpath的LRUCache
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.apache.flink.table.shaded.com.jayway.jsonpath.spi.cache;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.flink.table.shaded.com.jayway.jsonpath.JsonPath;
public class LRUCache implements Cache {
private final ReentrantLock lock = new ReentrantLock();
private final Map<String, JsonPath> map = new ConcurrentHashMap();
private final Deque<String> queue = new LinkedList();
private final int limit;
public LRUCache(int limit) {
this.limit = limit;
}
public void put(String key, JsonPath value) {
JsonPath oldValue = (JsonPath)this.map.put(key, value);
if (oldValue != null) {
this.removeThenAddKey(key);
} else {
this.addKey(key);
}
if (this.map.size() > this.limit) {
this.map.remove(this.removeLast());
}
}
public JsonPath get(String key) {
JsonPath jsonPath = (JsonPath)this.map.get(key);
if (jsonPath != null) {
this.removeThenAddKey(key);
}
return jsonPath;
}
private void addKey(String key) {
this.lock.lock();
try {
this.queue.addFirst(key);
} finally {
this.lock.unlock();
}
}
private String removeLast() {
this.lock.lock();
String var2;
try {
String removedKey = (String)this.queue.removeLast();
var2 = removedKey;
} finally {
this.lock.unlock();
}
return var2;
}
private void removeThenAddKey(String key) {
this.lock.lock();
try {
this.queue.removeFirstOccurrence(key);
this.queue.addFirst(key);
} finally {
this.lock.unlock();
}
}
private void removeFirstOccurrence(String key) {
this.lock.lock();
try {
this.queue.removeFirstOccurrence(key);
} finally {
this.lock.unlock();
}
}
...
}
可以看到get操作时,如果获取到的是有值的,那么会更新相应key的数据从双端队列移到首位,借此来实现LRU的功能,但是这样每次get和put操作都是需要加锁的,因此并发情况下吞吐就会比较低,也会导致cpu使用效率较低。
从jsonpath社区查看相应的问题,也有相关的反馈
https://github.com/json-path/JsonPath/issues/740
https://github.com/apache/pinot/pull/7409
比较方便的是,jsonpath 提供了spi的方式可以自定义的设置Cache的实现类,可以通过以下方式来设置新的cache实现。
static {
CacheProvider.setCache(new JsonPathCache());
}
从pinot的实现中,我们看到他是用了guava的cache来替换了默认的LRUCache实现,那么这样实现性能优化有多少呢,这里我们是用java的性能测试框架jmh来测试下性能提升的情况
性能测试
这里为了方便,直接在flink-benchmark工程里添加了两个benchmark的测试类.
GuavaCache
LRUCache
这里面需要注意,因为cache是进程级别共享的,所以我们需要将设置@State(Benchmark)
级别,这样我们构建的cache就是进程级别共享,而不是线程级别共享的。
写的测试是4个线程运行,缓存大小均为400
为了避免在本机运行时受本机的其他程序影响,最好是build jar之后放到服务器上跑
java -jar target/benchmarks.jar -rf csv org.apache.flink.benchmark.GuavaCacheBenchmark
得到一个测试结果
Benchmark Mode Cnt Score Error Units
GuavaCacheBenchmark.get thrpt 30 4480.563 ± 203.311 ops/ms
GuavaCacheBenchmark.put thrpt 30 1774.769 ± 119.198 ops/ms
LRUCacheBenchmark.get thrpt 30 441.239 ± 2.812 ops/ms
LRUCacheBenchmark.put thrpt 30 350.549 ± 12.285 ops/ms
可以看到使用guava的cache后,get性能提升8倍左右,put性能提升5倍左右。
这块性能提升的主要来源是cache的实现机制上,和caffeine 的作者在github上也简单了解了下相关的推荐实现
后面会写一篇文章来专门分析下caffeine cache的优化实现。
参考
https://github.com/ben-manes/caffeine/wiki/Benchmarks#read-100-1 caffeine benchmark
https://github.com/ben-manes/caffeine/blob/master/caffeine/src/jmh/java/com/github/benmanes/caffeine/cache/GetPutBenchmark.java caffeine benchmark
https://www.jianshu.com/p/ad34c4c8a2a3 jmh 框架常见参数
http://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-samples/src/main/java/org/openjdk/jmh/samples/ jmh 常见用例
使用jmh框架进行benchmark测试的更多相关文章
- IOS(SystemConfiguration)框架中关于测试连接网络状态相关方法
1. 在SystemConfiguration.famework中提供和联网相关的function, 可用来检查网络连接状态. 2. SC(SystemConfiguration)框架中关于测试连接网 ...
- Spring框架下Junit测试
Spring框架下Junit测试 一.设置 1.1 目录 设置源码目录和测试目录,这样在设置产生测试方法时,会统一放到一个目录,如果没有设置测试目录,则不会产生测试代码. 1.2 增加配置文件 Res ...
- [转帖]TPC-C解析系列01_TPC-C benchmark测试介绍
TPC-C解析系列01_TPC-C benchmark测试介绍 http://www.itpub.net/2019/10/08/3334/ 学习一下. 自从蚂蚁金服自研数据库OceanBase获得TP ...
- <自动化测试>之<使用unittest Python测试框架进行参数化测试>
最近在看视频时,虫师简单提到了简化自动化测试脚本用例中的代码量,而python中本身的参数化方法用来测试很糟糕,他在实际操作中使用了parameterized参数化... 有兴趣就查了下使用的方法,来 ...
- Java8 Stream代码详解+BenchMark测试
Java8 Stream基础.深入.测试 1.基本介绍 1.创建方式 1.Array的Stream创建 1.直接创建 // main Stream stream = Stream.of("a ...
- python实例编写(6)--引入unittest测试框架,构造测试集批量测试(以微信统一管理平台为例)
---恢复内容开始--- 一.python单元测试实例介绍 unittest框架又叫PyUnit框架,是python的单元测试框架. 先介绍一个普通的单元测试(不用unittest框架)的实例: 首先 ...
- 修改testtools框架,将测试结果显示用例注释名字
在之前介绍的测试框架testtool中,发现测试结果中显示的都是测试用例的函数名,并没有将注释显示出来 这很不符合国人使用阿,没办法,自己动手来改改吧 首先,testtools是继承unittest的 ...
- 框架重构:测试中的DateTime.Now
存在的问题 DateTime.Now是C#语言中获取计算机的当前时间的代码: 但是,在对使用了DateTime.Now的方法进行测试时,由于计算机时间的实时性,期望值一直在变化.如:计算年龄. pub ...
- YCSB benchmark测试mongodb性能——和web服务器测试性能结果类似
转自:http://blog.sina.com.cn/s/blog_48c95a190102v9kg.html YCSB(Yahoo! Cloud Serving Benchmark) ...
随机推荐
- JAVA数组案例!
数组的用例 一.案例需求: 有这样的一个数组,元素是{68,27,95,88,171,996,51,210}.求出该数组中满足要求的元素和, 要求是:求和的元素个位和十位都不能是7,并且只能是偶数如何 ...
- forms组件补充与ModelForm简单使用与cookie与session
目录 forms组件钩子函数 forms组件字段参数 字段参数 validators详解 choices详解 widget详解 forms组件字段类型 ModelForm简单使用 cookie与ses ...
- find-文件搜索
根据条件搜索文件. 语法 find 目录 [选项] 选项 -name <filename> 按文件目录名查找.文件目录名可使用通配符"*",即表示模糊匹配所有字符. - ...
- C# 四舍五入中一处易错点
,你没看错,四舍五入的结果 和我们期待的不太一样 Why?? 进入源码看下,注释中解释的很清楚.. 默认情况下,Math.Round()方法返回的是最接近的整数,这个没问题,问题是当要转换的数据在 两 ...
- Microsoft Office 代码执行漏洞临时防范方法
一.删除ms-msdt URI 注册表 1.按下键盘上的快捷组合键:win键 和 R键,打开运行(也可以在开始菜单打开运行). 2.在运行窗口中输入命令:regedit,点击确定或敲回车键就可以快速打 ...
- MySQL - 数据库设计步骤
需求分析:分析用户的需求,包括数据.功能和性能需求. 概念结构设计:主要采用E-R模型进行设计,包括画E-R图. 逻辑结构设计:通过将E-R图转换成表,实现从E-R模型到关系模型的转换,进行关系规范化 ...
- 回流&重绘
浏览器加载解析页面:把HTML解析为DOM树,解析CSS生成CSSOM树,HTML DOM树和CSSOM树组合构建render树,首次触发回流和重绘后将页面结构信息发送给GPU进行绘制渲染. 回流:当 ...
- Nginx安装及支持https代理配置和禁用TSLv1.0、TSLv1.1配置
Linux安装Nginx Nginx安装及支持https代理配置和禁用TSLv1.0.TSLv1.1配置. 下载安装包 [root@localhost ~]# wget http://nginx.or ...
- C#实现[移除文件名中的非中文字符]
更新记录: 2022年5月28日 从程序中抽出方法复用. 处理财务文件时写的一个小函数.用于移除文件名中的非中文字符. /// <summary> /// 移除文件名中的非中文字符 /// ...
- 南京大学 静态软件分析(static program analyzes)-- introduction 学习笔记
一.Programming Languages体系 静态程序分析是编程语言中应用层面下的一个细分领域,它是一个非常重要的核心内容. 在理论部分,考虑的是如何设计一个语言的语法和语义,如何设计语言的类型 ...