- 浏览: 182014 次
文章分类
最新评论
-
luxing44530:
你好, 关于 JDK 7中也有一个支持协程方式的实现 在那呀? ...
Java性能调优笔记 -
songgz:
你是一个会思考的人,前途无量,代码审查显然不能以风格和规则为主 ...
到底该怎么样做代码审查? -
jiaoronggui:
遇到过一模一样的问题
一条Select语句导致瓶颈 -
Leon.Wood:
写出让计算机读懂的代码很容易,写出让人读懂的只有高手才能做到. ...
到底该怎么样做代码审查? -
ajuanlove:
不经常用这玩意
对300万一张表数据,用游标进行循环,不同写法的效率比较
调优步骤:衡量系统现状、设定调优目标、寻找性能瓶颈、性能调优、衡量是否到达目标(如果未到达目标,需重新寻找性能瓶颈)、性能调优结束。
寻找性能瓶颈
性能瓶颈的表象:资源消耗过多、外部处理系统的性能不足、资源消耗不多但程序的响应速度却仍达不到要求。
资源消耗:CPU、文件IO、网络IO、内存。
外部处理系统的性能不足:所调用的其他系统提供的功能或数据库操作的响应速度不够。
资源消耗不多但程序的响应速度却仍达不到要求:程序代码运行效率不够高、未充分使用资源、程序结构不合理。
一、CPU消耗分析
CPU主要用于中断、内核、用户进程的任务处理,优先级为中断>内核>用户进程。
上下文切换:
每个线程分配一定的执行时间,当到达执行时间、线程中有IO阻塞或高优先级线程要执行时,将切换执行的线程。在切换时要存储目前线程的执行状态,并恢复要执行的线程的状态。
对于Java应用,典型的是在进行文件IO操作、网络IO操作、锁等待、线程Sleep时,当前线程会进入阻塞或休眠状态,从而触发上下文切换,上下文切换过多会造成内核占据较多的CPU的使用。
运行队列:
每个CPU核都维护一个可运行的线程队列。系统的load主要由CPU的运行队列来决定。
运行队列值越大,就意味着线程会要消耗越长的时间才能执行完成。
利用率:
CPU在用户进程、内核、中断处理、IO等待、空闲,这五个部分使用百分比。
CPU消耗严重的解决方法
CPU us高的解决方法:
CPU us 高的原因主要是执行线程不需要任何挂起动作,且一直执行,导致CPU 没有机会去调度执行其他的线程。
调优方案: 增加Thread.sleep,以释放CPU 的执行权,降低CPU 的消耗。以损失单次执行性能为代价的,但由于其降低了CPU 的消耗,对于多线程的应用而言,反而提高了总体的平均性能。
(在实际的Java应用中类似场景, 对于这种场景最佳方式是改为采用wait/notify机制)
对于其他类似循环次数过多、正则、计算等造成CPU us过高的状况, 则需要结合业务调优。
对于GC频繁,则需要通过JVM调优或程序调优,降低GC的执行次数。
CPU sy高的解决方法:
CPU sy 高的原因主要是线程的运行状态要经常切换,对于这种情况,常见的一种优化方法是减少线程数。
调优方案: 将线程数降低
这种调优过后有可能会造成CPU us过高,所以合理设置线程数非常关键。
对于Java分布式应用,还有一种典型现象是应用中有较多的网络IO操作和确实需要一些锁竞争机制(如数据库连接池),但为了能够支撑搞得并发量,可采用协程(Coroutine)来支撑更高的并发量,避免并发量上涨后造成CPU sy消耗严重、系统load迅速上涨和系统性能下降。
在Java中实现协程的框架有Kilim,Kilim执行一项任务创建Task,使用Task的暂停机制,而不是Thread,Kilim承担了线程调度以及上下切换动作,Task相对于原生Thread而言就轻量级多了,且能更好利用CPU。Kilim带来的是线程使用率的提升,但同时由于要在JVM堆中保存Task上下文信息,因此在采用Kilim的情况下要消耗更多的内存。(目前JDK 7中也有一个支持协程方式的实现,另外基于JVM的Scala的Actor也可用于在Java使用协程)
二、文件IO、网络IO
文件IO消耗分析
Linux在操作文件时,将数据放入文件缓存区,直到内存不够或系统要释放内存给用户进程使用。所以通常情况下只有写文件和第一次读取文件时会产生真正的文件IO。
对于Java应用,造成文件IO消耗高主要是多个线程需要进行大量内容写入(例如频繁的日志写入)的动作、磁盘设备本身的处理速度慢、文件系统慢、操作的文件本身已经很大。
从程序的角度而言,造成文件IO消耗严重的原因主要是多个线程在写进行大量的数据到同一文件,导致文件很快变得很大,从而写入速度越来越慢,并造成各线程激烈争抢文件锁。
常用调优方法:
异步写文件
批量读写
限流
限制文件大小
网络IO消耗分析
对于分布式Java应用,网卡中断是不是均衡分配到各CPU(cat/proc/interrupts查看)。
网络IO消耗严重的解决方法
从程序的角度而言,造成网络IO消耗严重的原因主要是同时需要发送或接收的包太多。
常用调优方法:
限流,限流通常是限制发送packet的频率,从而在网络IO消耗可接受的情况下来发送packget。
三、内存
释放不必要的引用:代码持有了不需要的对象引用,造成这些对象无法被GC,从而占据了JVM堆内存。(使用ThreadLocal:注意在线程内动作执行完毕时,需执行ThreadLocal.set把对象清除,避免持有不必要的对象引用)
使用对象缓存池:创建对象要消耗一定的CPU以及内存,使用对象缓存池一定程度上可降低JVM堆内存的使用。
采用合理的缓存失效算法:如果放入太多对象在缓存池中,反而会造成内存的严重消耗, 同时由于缓存池一直对这些对象持有引用,从而造成Full GC增多,对于这种状况要合理控制缓存池的大小,避免缓存池的对象数量无限上涨。(经典的缓存失效算法来清除缓存池中的对象:FIFO、LRU、LFU等)
合理使用SoftReference和WeekReference:SoftReference的对象会在内存不够用的时候回收,WeekReference的对象会在Full GC的时候回收
四、资源消耗不多但程序执行慢的情况的解决方法
降低锁竞争: 多线多了,锁竞争的状况会比较明显,这时候线程很容易处于等待锁的状况,从而导致性能下降以及CPU sy上升。
使用并发包中的类:大多数采用了lock-free、nonblocking算法。
使用Treiber算法:基于CAS以及AtomicReference。
使用Michael-Scott非阻塞队列算法:基于CAS以及AtomicReference,典型ConcurrentLindkedQueue。
(基于CAS和AtomicReference来实现无阻塞是不错的选择,但值得注意的是,lock-free算法需不断的循环比较来保证资源的一致性的,对于冲突较多的应用场景而言,会带来更高的CPU消耗,因此不一定采用CAS实现无阻塞的就一定比采用lock方式的性能好。 还有一些无阻塞算法的改进:MCAS、WSTM等)
尽可能少用锁:尽可能只对需要控制的资源做加锁操作(通常没有必要对整个方法加锁,尽可能让锁最小化,只对互斥及原子操作的地方加锁,加锁时尽可能以保护资源的最小化粒度为单位--如只对需要保护的资源加锁而不是this)。
拆分锁:独占锁拆分为多把锁(读写锁拆分、类似ConcurrentHashMap中默认拆分为16把锁),很多程度上能提高读写的性能,但需要注意在采用拆分锁后,全局性质的操作会变得比较复杂(如ConcurrentHashMap中size操作)。(拆分锁太多也会造成副作用,如CPU消耗明显增加)
去除读写操作的互斥:在修改时加锁,并复制对象进行修改,修改完毕后切换对象的引用,从而读取时则不加锁。这种称为CopyOnWrite,CopyOnWriteArrayList是典型实现,好处是可以明显提升读的性能,适合读多写少的场景, 但由于写操作每次都要复制一份对象,会消耗更多的内存。
充分利用硬件资源(CPU和内存):
充分利用CPU
在能并行处理的场景中未使用足够的线程(线程增加:CPU资源消耗可接受且不会带来激烈竞争锁的场景下), 例如单线程的计算,可以拆分为多个线程分别计算,最后将结果合并,JDK 7中的fork-join框架。
Amdahl定律公式:1/(F+(1-F)/N)。
充分利用内存
数据的缓存、耗时资源的缓存(数据库连接创建、网络连接的创建等)、页面片段的缓存。
毕竟内存的读取肯定远快于硬盘、网络的读取, 在内存消耗可接受、GC频率、以及系统结构(例如集群环境可能会带来缓存的同步)可接受情况下,应充分利用内存来缓存数据,提升系统的性能。
总结:
好的调优策略是收益比(调优后提升的效果/调优改动所需付出的代价)最高的,通常来说简单的系统调优比较好做,因此尽量保持单机上应用的纯粹性, 这是大型系统的基本架构原则。
调优的三大有效原则:充分而不过分使用硬件资源、合理调整JVM、合理使用JDK包。
更多信息请查看 java进阶网 http://www.javady.com
发表评论
-
Java性能调优方法:基于等待的调优(四)
2012-04-14 21:33 805基于技术的等待 ... -
Java性能调优方法:基于等待的调优(三)
2012-04-14 21:33 883基于等待的调优 ... -
Java性能调优工具“JRMC”的介绍
2012-04-11 13:00 890Java虚拟机(JVM)及垃圾收集器(GC)负责管理大多数 ... -
java代码性能优化四
2012-04-10 13:17 2289正确的字符串比较 字符串比较方法的性能 ... -
java代码性能优化三
2012-04-10 13:14 1273使用局部缓存 在 DA ... -
java代码性能优化二
2012-04-09 10:19 915正确使用递归 递归算法可以清晰表达复杂的算法,提高代码 ... -
java代码性能优化一
2012-04-09 10:18 1528使用正确的集合类 在我们的代码中常用的 ... -
Java中的IO的性能优化
2012-04-15 23:08 1445Java中的IO的性能优化 在使用IO的时候注意一下细节,能 ... -
Java性能调优
2012-04-14 21:32 820一 基本知识 1.1 性能是什么 在性能调 ... -
Java性能调优方法:基于等待的调优(五)
2012-04-14 21:32 674后退调优 现在 ... -
Java性能调优方法:基于等待的调优(四)
2012-04-15 23:08 691基于技术的等待点 ... -
Java性能调优方法:基于等待的调优(三)
2012-04-15 23:08 600基于等待的调优方法 建好了负载测试,接下 ... -
Java性能调优方法:基于等待的调优(二)
2012-04-12 22:01 762已存在应用 ... -
Java性能调优方法:基于等待的调优(一)
2012-04-12 22:01 694企业java应用的性能调优是一项艰巨的、有时甚至是徒劳的 ... -
Java性能调优工具
2012-04-12 22:01 823作为一名Java ... -
Java垃圾回收调优
2012-04-12 22:01 724在Java中,通常通讯类型的服务器对GC(Garbage Co ... -
Java性能调优工具“JRMC”的介绍
2012-04-12 22:01 794Java虚拟机(JVM)及垃圾收集器(GC)负责管理大多数 ... -
java代码性能优化四
2012-04-08 23:03 0正确的字符串比较 字符串比较 ... -
java代码性能优化三
2012-04-08 23:02 0使用局部缓存 在 DALC 方法中,很多地方需要对 ... -
java代码性能优化二
2012-04-08 22:59 0正确使用递归 递归算法可以清晰表达复杂的算法,提高代码 ...
相关推荐
阿里巴巴Java性能调优华山版是一套系统性能调优教程,!通过这份笔记的学习,你将会有一个系统的调优头脑和策略!快了何止100%?需要的朋友可下载试试! 众所周知性能调优可以使系统稳定,用户体验更佳,甚至在...
该资源为老师JVM调优讲解完整版课件,现在分享给大家,希望对与想进阶java的小伙伴带来帮助
JVM 面试题:Java 类加载过程、JVM 加载 Class 文件的原理机制、Java内存分配
Java 虚拟机学习笔记: Java 内存区域, 垃圾收集, 内存分配与回收策略, JVM 调优, 文件结构, 类加载机制, Java 程序 Java是一种面向对象的编程语言,由Sun Microsystems于1995年推出。它是一种跨平台的语言,...
java 性能调优,jvm 工具定位 深入解析
https://coding.imooc.com/learn/list/241.html这个课程的笔记,私人整理的,挺好的
JVM与GC调优课程视频 ...├── 第8篇-JVM性能调优案例篇.png?x-oss-process=style/pnp8 └── 下载必读.txt 2.资料/ ├── apache-jmeter-5.4.1.zip ├── arthas-boot.jar ├── arthas-master.zip ├──
高级java笔试题 StudySpark spark的一个小项目以及笔记 目录 项目内容 用户访问session分析模块 用户访问session分析业务,session...性能调优方案:普通调优、jvm调优、shuffle调优、算子调优 troubleshooting经验 数
│ JVM性能调优 2018-10-25.mp4 │ ├─面试必问-mybaits源码分析 │ │ 鲁班学院-上课笔记mybaits源码分析9-05.docx │ │ │ └─mybaits源码分析 │ mybaits源码分析.mp4 │ ├─面试必问-springcloud架构...
Java优化编程(第2版)通过丰富、完整、富有代表性的实例,展示了如何提升Java应用性能,并且给出了优化前与优化后的Java应用程序的性能差别,以实际的实例与数字告诉你,为什么不可以这么做,应该怎么做,深入分析...
1000道 互联网Java工程师面试题 485页 .pdf Docker — 从入门到实践.pdf Java中高级核心知识全面解析.pdf ...MySQL性能调优与架构设计解析文档.pdf Nginx入门到实战.pdf springCloud笔记.pdf Spring高级源码笔记.pdf
主要是JVM内存分配及简单的JVM性能调优
三:下篇——性能监控与调优篇 一: 上篇——内存与垃圾回收器 架构: jvm依赖的架构: 栈架构/寄存器架构 栈架构 JVM的生命周期: 1.启动 通过引导类加载器(Bootstrap class loader)创建一个初始类(Initial Class)来...
大厂架构师-日均百万订单量的JVM优化与高级GC调优策略实战(5.8G) 〖课程介绍〗: 来自顶尖大厂的架构师级JVM优化与GC调优策略实战课程,是具备有尖端技术的优化课程。...├─第7篇-JVM性能监控篇.png?x-oss-process=styl
运行时数据区域、垃圾收集、内存分配机制、类加载机制、性能调优监控工具 Java 设计模式 Java 常见的 10 余种设计模式,全 23 种设计模式逐步更新 Java Web 包含 Servlet & JSP、Spring、SpringMVC、Mybatis、...
java8 集合源码分析 ...运行时数据区域、垃圾收集、内存分配机制、类加载机制、性能调优监控工具 Java 常见的 10 余种设计模式,全 23 种设计模式逐步更新 包含 Servlet & JSP、Spring、SpringMVC、My
学习笔记较长,如果想查看文章的目录,chrome浏览器可以配合简悦插件使用,或者下载到本地使用Typora打开。 :hot_beverage: Java基础 Java容器 Java并发 数据结构和算法 数据结构 树 图 算法 分治 动态规划 回溯 ...
虚拟机性能监控与故障处理工具 内存溢出问题及调优 类文件结构 虚拟机类加载机制 编译期编译优化 运行期优化 高效并发-java内存模型与线程 线程安全与锁优化 1 标记-清除算法:首先标记所有需要回收的对象(引用计数...
性能调优工具 服务发现 service mesh 分布式框架 权限引擎 模板引擎 依赖注入 ORM 日志 搜索引擎 爬虫 数据校验 restful 消息中间件 响应式编程 热加载 数据库连接池 测试工具 序列化 数据库工具 服务发现 配置相关 ...
Android 学习笔记之 SQLite基础用法 如何充分利用 Windows Phone 高清屏幕 【cocos2d-x 手游研发----博彩大转盘】 后端架构 回顾2013:HBase的提升与挑战 memcached(十七)协议命令格式 nginx大流量负载调优 12306...