首页 文章 精选 留言 我的

精选列表

搜索[jdk8],共893篇文章
优秀的个人博客,低调大师

每日一博 | 使用 perf 解决 JDK8 小版本升级后性能下降的问题

编者按:在升级 JDK8U 的小版本后(从 8u74 升级到 8u202),遇到性能剧烈下降的问题(性能下降 13 倍)。该应用是一个非常简单的 Web 应用,且应用在 JDK 升级前后并无任何发布修复。通常来说 JDK 小版本升级都是问题修改,不影响功能和性能使用,而应用性能剧烈下降一定是 JDK 的内部 bug。对于这样明确由 JDK 引起的性能问题,该如何解决?最常见的方法是通过工具分析 JVM 执行过程,检查函数执行的情况是否发生变化,如果找到变化,则可以深入分析哪些因素引起了变化,并进一步得到根因。笔者使用 perf 工具分析 JVM 执行时的热点函数,并对出现问题的函数进行剖析,使用函数插桩来分析函数的执行次数,发现不同版本行为差异的根源,并找到了引起问题的根因。希望读者遇到性能问题时可以参照本文使用 perf 工具对问题进行定位。 工欲善其事,必先利其器。程序员在定位性能瓶颈的时候,要是有一个趁手的性能调优工具,能一针见血地指出程序的性能问题,可谓事半功倍。 Linux 中最常用的性能调优工具 Perf(Linux 系统原生提供的性能分析工具),使用 perf 先对应用(假设要采样的应用为 JavaApp)进行采样,使用 record 命令,如下: perfrecordjavaJavaApp 另外 perf 能按出现的百分比降序打印 CPU 正在执行的函数名以及调用栈,如命令: perfreport-n 可打印出: 这种结果的输出还是不直观的,Linux 性能优化大师 Brendan Gregg 发明了火焰图(因整个图形看起来像燃烧的火焰而得名),以全局的方式来看各个函数的调用时间分布,以图形化的方式列出调用栈。 初识火焰图 火焰图是基于 perf 的结果生成的图形,我们先了解一下怎么去看火焰图。以下图为例: X 轴表示被抽样到的次数。理解 X 轴的含义,需先了解采样数据的原理。Perf 是在指定时间段内,每隔一段时间采集一次数据,被采集到的次数越多,说明该函数的执行总时间长,可能的原因有:调用次数多,或者单次执行时间长。因此,X 轴的宽度不能简单的认为是运行时长。Y 轴表示调用栈。 如何从火焰图看出性能的瓶颈在哪里?最有理由怀疑的地方,顶层的“平顶”。关于 perf 和火焰图使用方法可以参官网http://www.brendangregg.com/FlameGraphs/cpuflamegraphs.html。 下面是我们利用火焰图来定位问题的一次实战。 火焰图定位问题的实战 问题场景 问题发生的场景是客户端向服务器发起 http 请求,服务器返回数据给客户端(这是一个非常简单的服务交互)。我们发现使用 JDK 8u74 的性能要远优于 JDK 8u202 的性能,下表中统计了 20 次服务器的响应时长。 从响应时间来看,8u202 相比 8u74 性能下降 13 倍之多,由于应用本身并未做任何修改,所以考虑使用火焰图来定位性能消耗的问题点。在 8u74 和 8u202 分别运行应用,并用 perf 的 record 抓取数据并生成火焰图。 火焰图定位 对比两张火焰图,使用 8u74 时 ClientHandshaker.processMessage 占比为 1.15%,而在 8u202 中这个函数占比为 23.98%,很明显在 ClientHandshaker.processMessage 带来了性能差异。 根因定位 两者在这个 ClientHandshaker.processMessage 上的 cpu 消耗差异很大,继续分析这个函数找到根因。 voidprocessMessage(bytehandshakeType,intlength)throwsIOException{if(this.state>=handshakeType&&handshakeType!=0){//...异常}else{label105:switch(handshakeType){case0://hello_requestthis.serverHelloRequest(newHelloRequest(this.input));break;//...case2://sever_hellothis.serverHello(newServerHello(this.input,length));break;case11:///certificatethis.serverCertificate(newCertificateMsg(this.input));this.serverKey=this.session.getPeerCertificates()[0].getPublicKey();break;case12://server_key_exchange该消息并不是必须的,取决于协商出的key交换算法//...case13://certificate_request客户端双向验证时需要//...case14://server_hello_donethis.serverHelloDone(newServerHelloDone(this.input));break;case20://finishedthis.serverFinished(newFinished(this.protocolVersion,this.input,this.cipherSuite));}if(this.state<handshakeType){//握手状态this.state=handshakeType;}}} processMessage()主要是通过不同的信息类型进行不同的握手消息的处理。而在火焰图中可以看到,JDK8u74 图中,主要消耗在函数 serverFinished()和 serverHello()上,而 JDK8u202 主要消耗在函数 serverHelloDone()和 serverKeyExchange()。在介绍火焰图的时候,我们有提到,X 轴的长度是映射了被采样到的次数。因此需要进一步确定消耗:函数单次执行耗时过长而成为热点,还是因为频繁调用函数导致函数耗时过长而成为热点。可通过字节码插桩(通过 Instrument 技术实现对函数的计数,然后编译成 agent,执行应用时加载 agent,具体使用 Instrument 的方法可以参考官方文档)查看函数 serverHelloDone()的调用次数及执行时间。 JDK8u202数据Executecount:253Executecount:258Executecount:649Executecount:661serverHelloDoneexecutetime[1881195ns]Executecount:1223Executecount:1234Executecount:1843Executecount:1852serverHelloDoneexecutetime[1665012ns]Executecount:2446Executecount:2456serverHelloDoneexecutetime[1686206ns]JDK8u74数据Executecount:56Executecount:56Executecount:56Executecount:56Executecount:56Executecount:56 Execute time 是取了每 1000 次调用的平均值,Execute count 每 5000ms 输出一次总执行次数。很明显使用 JDK8u202 时在不断调用 serverHelloDone,而 74 在调用 56 次后没有再调用过这个函数。 初始化握手时,serverHelloDone 方法中,客户端会根据服务端返回加密套件决定加密方式,构造不同的 Client Key Exchange 消息;服务器如果允许重用该会话,则通过在 Server Hello 消息中设置相同的会话 ID 来应答。这样,客户端和服务器就可以利用原有会话的密钥和加密套件,不必重新协商,也就不再走 serverHelloDone 方法。从现象来看, JDK8u202 没有复用会话,而是建立的新的会话。 水落石出 查看 JDK8u 161 的 release notes,添加了 TLS 会话散列和扩展主密钥扩展支持,找到引入的一个还未修复的 issue,对于带有身份验证的 TLS 的客户端,支持 UseExtendedMasterSecret 会破坏 TLS-Session 的恢复,导致不使用现有的 TLS-Session,而执行新的 Handshake。 JDK8u161 之后的版本(含 JDK8u161),若复用会话时不能成功恢复 Session,而是创建新的会话,会造成较大性能消耗,且积压的大量的不可复用的 session 造成 GC 压力变大;如果业务场景存在不变更证书密钥,需要复用会话,且对性能有要求,可通过添加参数-Djdk.tls.useExtendedMasterSecret=false 来解决这个问题。 后记 如果遇到相关技术问题(包括不限于毕昇 JDK),可以通过毕昇 JDK 社区求助。毕昇 JDK 社区每双周周二举行技术例会,同时有一个技术交流群讨论 GCC、LLVM 和 JDK 等相关编译技术,感兴趣的同学可以添加如下微信小助手入群(请备注:Complier)。 本文分享自微信公众号 - openEuler(openEulercommunity)。如有侵权,请联系 support@oschina.cn 删除。本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

优秀的个人博客,低调大师

Linux系统:centos7下安装Jdk8、Tomcat8、MySQL5.7环境

本文源码:GitHub·点这里 || GitEE·点这里 一、JDK1.8 环境搭建 1、上传文件解压 [root@localhost mysoft]# tar -zxvf jdk-8u161-linux-x64.tar.gz [root@localhost mysoft]# pwd /usr/local/mysoft [root@localhost mysoft]# mv jdk1.8.0_161 jdk1.8 2、检查环境,已经安装删除 [root@localhost mysoft]# ps -aux|grep java [root@localhost mysoft]# rpm -e --nodeps rpm -qa | grep java 3、配置环境变量 [root@localhost /]# vim /etc/profile # 文件末尾追加 下面内容 shit+g 跳到文件末尾 # JAVA_HOME export JAVA_HOME=/usr/local/mysoft/jdk1.8 export PATH=$PATH:$JAVA_HOME/bin 4、检测安装成功 [root@localhost /]# java -version openjdk version "1.8.0_161" OpenJDK Runtime Environment (build 1.8.0_161-b14) OpenJDK 64-Bit Server VM (build 25.161-b14, mixed mode) 二、TOMCAT8 安装 1、上传安装包 [root@localhost mysoft]# tar -zxvf apache-tomcat-8.5.40.tar.gz [root@localhost mysoft]# mv apache-tomcat-8.5.40 tomcat8.5 2、启动服务 [root@localhost bin]# pwd /usr/local/mysoft/tomcat8.5/bin [root@localhost bin]# ./startup.sh Tomcat started. 3、访问测试 http://127.0.0.1:8080/ OK了 三、MySQL5.7 安装 1、卸载原系统中的mariadb [root@localhost /]# rpm -qa|grep mariadb mariadb-libs-5.5.56-2.el7.x86_64 [root@localhost /]# rpm -e --nodeps mariadb-libs [root@localhost /]# rpm -qa|grep mariadb 2、获取官方地址 地址:https://dev.mysql.com/downloads/repo/yum/ https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm 3、Yum源安装 wget https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm [root@localhost /]# rpm -ivh mysql80-community-release-el7-3.noarch.rpm [root@localhost /]# yum repolist all|grep mysql mysql57-community/x86_64 MySQL 5.7 Community Server disabled mysql80-community/x86_64 MySQL 8.0 Community Server enabled: 113 mysql80-community-source MySQL 8.0 Community Server - disabled …….. yum源中默认启用的安装包版本为MySQL8.0,这里切换为5.7,执行以下命令; [root@localhost /]# yum-config-manager --disable mysql80-community [root@localhost /]# yum-config-manager --enable mysql57-community 4、MySQL 安装启动 [root@localhost /]# yum install mysql-community-server # 需要安装依赖提示,选择y Total download size: 192 M Installed size: 865 M Is this ok [y/d/N]: y 查看版本 [root@localhost /]# mysql -V mysql Ver 14.14 Distrib 5.7.26, for Linux (x86_64) using EditLine wrapper 启动查看状态 [root@localhost /]# systemctl start mysqld.service [root@localhost /]# systemctl status mysqld.service mysqld.service - MySQL Server Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled) Active: active (running) since Tue 2019-05-14 17:26:32 CST; 31s ago 为root账户生成临时密码 [root@localhost /]# grep 'temporary password' /var/log/mysqld.log 2019-05-14T09:26:28.657250Z 1 [Note] A temporary password is generated for root@localhost: !Bh(GT.od9L; 设置root用户密码 # 这里防止出现密码策略,强度不够的问题 mysql> set global validate_password_policy=LOW; mysql> alter user 'root'@'localhost' identified by 'husky123456'; 这样,Java的基础环境就搭建完毕了! 四、源代码地址 GitHub·地址 https://github.com/cicadasmile/linux-system-base GitEE·地址 https://gitee.com/cicadasmile/linux-system-base

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册