在多线程读58万数据处理后写入到另外一张表中性能调优实例遇到第一个问题就是drools的性能瓶颈,对CPU消耗比加大,那么如何优化呢?

从下图看到i5-8250U的计算能力应该不行,这个时候终于知道cpu好,会能起到什么效果了。

使用arthas可以定位到,有两个地方耗费时间Results results = kieHelper.verify();KieBase kieBase = kieHelper.build(config);

public KieSession decodeToSession(String... drl) {KieHelper kieHelper = new KieHelper();String[] var3 = drl;int var4 = drl.length;for(int var5 = 0; var5 < var4; ++var5) {String s = var3[var5];kieHelper.addContent(s, ResourceType.DRL);}Results results = kieHelper.verify();if (results.hasMessages(new Level[]{Level.WARNING, Level.ERROR})) {List<Message> messages = results.getMessages(new Level[]{Level.WARNING, Level.ERROR});Iterator var11 = messages.iterator();while(var11.hasNext()) {Message message = (Message)var11.next();this.logger.error("Error: {}", message.getText());}throw new IllegalStateException("Compilation errors.");} else {KieBaseConfiguration config = kieHelper.ks.newKieBaseConfiguration();if (EventProcessingOption.STREAM.getMode().equalsIgnoreCase(this.getMode())) {config.setOption(EventProcessingOption.STREAM);} else {config.setOption(EventProcessingOption.CLOUD);}KieBase kieBase = kieHelper.build(config);KieSession kieSession = kieBase.newKieSession();if (this.getListener() == null || !"off".equalsIgnoreCase(this.getListener())) {kieSession.addEventListener(new DefaultRuleRuntimeEventListener());kieSession.addEventListener(new DefaultAgendaEventListener());kieSession.addEventListener(new DefaultProcessEventListener());}return kieSession;}}

先看KieHelper.verify,对规则的校验并不总是需要,那么设置一个规则,校验过的不再校验,这个时间就节省了。

public KieSession getKieSession(List<String> ruleFileNames){if (CollectionUtils.isEmpty(ruleFileNames)){throw new NullPointerException("ruleFileNames is null");}List<String> rules = new ArrayList<>();Long start = System.currentTimeMillis();for (String ruleFileName:ruleFileNames){// 从缓存中获取内容String rule = cacheService.get(ruleFileName);if (StringUtils.isBlank(rule)){// 缓存中没有取到数据,这种情况是针对新增的文件,在cache中还没有存在,定时任务还没有刷到,则主动加载rule = loadAppointRule(ruleFileName);rules.add(rule);} else {if (Constants.ON.equals(cacheService.get(ruleFileName+Constants.FLAG))){// 缓存没有变化,就不需要再校验了,因为loadAppointRule的时候已经verify了rules.add(rule);log.info("文件:{},缓存命中",ruleFileName);} else{log.info("文件:{},缓存没有命中",ruleFileName);// 缓存发生变化,需要再次verifyif (verify(rule)){// 校验通过的标志cacheService.put(ruleFileName+Constants.FLAG,Constants.ON);rules.add(rule);} else{throw new IllegalArgumentException("ruleFileName verify error");}}}}Long end = System.currentTimeMillis();log.info("load rule 总耗时:{}ms",end-start);// 构建KieSessionstart = System.currentTimeMillis();KieSession kieSession = buildKieSession(rules);end = System.currentTimeMillis();log.info("buildKieSession 总耗时:{}ms",end-start);return kieSession;}

加载文件,校验通过之后,就存入缓存,并设置校验通过标志位,这个时间就节省掉了。

private String loadAppointRule(String fileName) {List<File> fileList = getAllRuleFiles();for (File file : fileList) {if (fileName.equals(file.getName())) {String rule = encodeToString(file.getPath());// 校验加载的规则文件是否合法if (verify(rule)){// 将正确的规则文件写入到缓存中cacheService.put(fileName, rule);// 校验通过的标志cacheService.put(fileName+Constants.FLAG,Constants.ON);} else{log.error("规则文件:{},存在异常,请注意核查",fileName);}return rule;}}return null;}

继续跟踪,发现耗时还是getKieSession

问题出现下面的代码,那么该如何优化呢?

private KieSession buildKieSession(List<String> rules){KieHelper kieHelper = new KieHelper();for (String rule : rules) {kieHelper.addContent(rule, ResourceType.DRL);}KieBaseConfiguration config = kieHelper.ks.newKieBaseConfiguration();if (EventProcessingOption.STREAM.getMode().equalsIgnoreCase(getMode())) {config.setOption(EventProcessingOption.STREAM);} else {config.setOption(EventProcessingOption.CLOUD);}KieBase kieBase = kieHelper.build(config);KieSession kieSession = kieBase.newKieSession();if (getListener() == null || !Constants.OFF.equalsIgnoreCase(getListener())) {kieSession.addEventListener(new DefaultRuleRuntimeEventListener());kieSession.addEventListener(new DefaultAgendaEventListener());kieSession.addEventListener(new DefaultProcessEventListener());}return kieSession;}

换了一台i5-9400的,buildKieSession 总耗时:2350ms,相比i5-8250U,快了8倍以上,确实难以想象。

drools的线程数量,跟CPU核数有关系

我们知道有状态的kiesession构建时间要比无状态的statelesskiesession长,那么如果是统一个规则,重复支持,这个状态保持住不就可以了吗?推理逻辑就是这样。
可以看到kiesession的编译时间骤降,性能很快提升上去了。

调整代码如下:

 @Overridepublic boolean matchByDay(LiuShiJiaZiEnum day) throws InvocationTargetException, IllegalAccessException {log.info(String.format("task %s start", day.display()));long start = System.currentTimeMillis();List<BaziInfo> baziInfos = baziInfoService.getByDay(day.display());// 获取kiesessionList<String> ruleList = new ArrayList<>();ruleList.add("shy3.xlsx");KieSession session = kieTemplate.getKieSession(ruleList);// 生成ShyGenYinDto dto = null;ShyGenyinQr shyGenyinQr = null;for (BaziInfo baziInfo: baziInfos){BaZi bazi = new BaZi.Builder().setYear(baziInfo.getYear()).setMonth(baziInfo.getMonth()).setDay(baziInfo.getDay()).setHour(baziInfo.getHour()).build();dto = qiangRuoService.getQiangRuo(session,bazi);shyGenyinQr = convert2Shy(dto);shyGenyinQr.setId(baziInfo.getFullBazi());//shyGenyinQrService.insertSelective(shyGenyinQr);}session.dispose();long end = System.currentTimeMillis();log.info("日柱{}:数量{},查询耗时{}", day.display(),baziInfos.size(), end-start);return true;}

再看CPU负载如下,降低很多了。

上图还有一个耗时的22.0% - 540 s org.apache.commons.beanutils.BeanUtils.copyProperties,这个地方用到了一个存在性能问题,参见几种copyProperties工具类性能比较
改用org.springframework.beans.BeanUtils,住一个这个跟apache的顺序刚好相反。再次测试发现spring的BeanUtils性能真是好。

换成我的i5-9400,发现线程是Net I/O状态,

查看CPU,打log都消耗了3.2%的CPU,如果想更快,这个块的日志都可以关掉

drools性能优化相关推荐

  1. kali2020进入单模式_蚂蚁集团技术专家山丘:性能优化的常见模式及趋势

    陈显铭(山丘) 读完需要 6分钟 速读仅需 2 分钟 陈显铭,花名山丘,就职于蚂蚁集团,对分布式应用架构.服务化.性能优化等有深入的理解.参与支付宝支付链路核心系统,设计.调优应用系统关键能力, 高效 ...

  2. MegEngine推理性能优化

    MegEngine推理性能优化 MegEngine「训练推理一体化」的独特范式,通过静态图优化保证模型精度与训练时一致,无缝导入推理侧,再借助工业验证的高效卷积优化技术,打造深度学习推理侧极致加速方案 ...

  3. asp.net程序性能优化的七个方面

    asp.net程序性能优化的七个方面 一.数据库操作 1.用完马上关闭数据库连接 访问数据库资源需要创建连接.打开连接和关闭连接几个操作.这些过程需要多次与数据库交换信息以通过身份验证,比较耗费服务器 ...

  4. java criteria限制条数_java架构—Oracle SQL性能优化

    (1) 选择最有效率的表名顺序(只在基于规则的优化器中有效): ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表 driving table)将被最先 ...

  5. ab测试nginx Nginx性能优化

    转自:https://www.cnblogs.com/nulige/p/9369700.html 1.性能优化概述 在做性能优化前, 我们需要对如下进行考虑 1.当前系统结构瓶颈 观察指标 压力测试 ...

  6. RHEL/CentOS通用性能优化、安全配置参考

    RHEL/CentOS通用性能优化.安全配置参考 本文的配置参数是笔者在实际生产环境中反复实践总结的结果,完全适用绝大多数通用的高负载.安全性要求的网络服务器环境.故可以放心使用. 若有异议,欢迎联系 ...

  7. Android开发——布局性能优化的一些技巧(一)

    0. 前言 上一篇我们分析了为什么LinearLayout会比RelativeLayout性能更高,意义在于分析了这两种布局的实现源码,算是对一个小结论的证明过程,但是对布局性能的优化效果,对这两种布 ...

  8. Web性能优化实践——应用层性能优化

    随着公司项目的进一步推广,用户数量的增加,已经面临着单台服务器不能负载的问题. 这次的优化由于时间关系主要分两步走,首先优化应用层代码以提高单台服务器的负载和吞吐率.之后再进行分表,引入队列.MemC ...

  9. 嵌入式linux内存使用和性能优化

    这本书有两个关切点:系统内存(用户层)和性能优化. 这本书和Brendan Gregg的<Systems Performance>相比,无论是技术层次还是更高的理论都有较大差距.但是这不影 ...

最新文章

  1. leetcode算法题--替换所有的问号
  2. hdu2722 简单最短路,处理好输入就行
  3. P13 最优控制系统-《Matlab/Simulink与控制系统仿真》程序指令总结
  4. react之bind函数到组件通识篇
  5. 笔记本电脑自带麦克风吗_小米电视可以唱歌吗
  6. winform datagridview 提高性能。
  7. C++之泛型编程(模板)
  8. python 多进程 每个进程做不同功能实例_Python 多进程并发操作中进程池Pool的实例...
  9. javaScript 判断一个数是不是质数(素数)
  10. java IO流学习总结
  11. SPSS典型相关分析(Canonical Correlation Analysis)案例(SPSS25最新版)
  12. Android shell 授权文件执行权限
  13. 使用css3实现一个超浪漫的新年倒计时
  14. 关于医院精确套打发票的实现
  15. python量化选股策略 源码_【一点资讯】Python实现行业轮动量化选股【附完整源码】...
  16. 安装Linux时grub2安装失败,尝试安装Ubuntu作为计算机唯一的操作系统时,我收到错误'grub-install/dev/sda failed'。 - Ubuntu问答...
  17. python读取数据出现UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc8 in position 0: invalid contin
  18. JF-3型防火门氧指数测定仪
  19. E. Selling Souvenirs
  20. 数据结构二:线性表的顺序结构实现

热门文章

  1. python decimal函数_Python之decimal模块的使用
  2. 【Java Sound】(一)Sampled包概述
  3. 编译Android版本的Poco库
  4. 数独游戏题解.(DFS)
  5. 炉石传说(NUPT-1969)
  6. 分布式技术一周技术动态 2016.05.22
  7. 面试 -> 使用一个循环合并两个有序数组为1个有序数组
  8. 【小家Spring】Spring注解驱动开发---向Spring Ioc容器中注册Bean的7种方式
  9. 仿网易新闻评论的楼层效果
  10. android button setbackgroundcolor,Xamarin(Android)中资源文件中的Button的SetBackgroundColor