JAVA性能调优
Posted BYITTD
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA性能调优相关的知识,希望对你有一定的参考价值。
前言
1.程序的性能如何表现
执行速度:程序的反应是否迅速,响应是否足够短
内存分配:内存分配是否合理,是否过多消耗内存,或者存在泄露。
负载承受能力:当系统压力上升时,系统的执行速度、响应时间的上升曲线是否平缓。
2.性能的参考指标
执行时间、CPU时间、内存分配、磁盘吞吐量、网络吞吐量、响应时间
3.性能瓶颈
磁盘IO、网络操作、CPU、异常、数据库、锁竞争、内存
性能调优的层次
1.设计调优
设计调优处于所有调优手段的上层,它往往需要在软件开发前进行。在软件开发之初,软件架构师就应该评估系统可能存在的各种潜在的问题,并给出合理的设计方案。设计调优对性能的影响也是最大的。如果说代码优化、JVM调优是对系统微观层面上“量”的优化,那么设计优化就是对系统在宏观层面上“质”的优化。
2.代码调优
3.JVM调优
java程序运行在JVM上的,对JVM优化能在一定程度上提升JAVA程序的性能。例如内存和GC的优化。
4.数据库调优
SQL优化。数据库配置优化。
================================
优化步骤
1.需要明确性能目标;
2.系统性能测试;
3.定位性能瓶颈;
4.定位代码;
5.分析问题,提供解决方案.
================================
设计优化
1.单例模式
1.饿汉式(直接初始化好,不能实现延迟加载);
2.懒汉式(要加同步代码块);
3.静态内部类(实现延迟加载)(类加载的时候,内部类没有创建)
2.代理模式
用于实现延迟加载;远程调用的网络代理;安全因素的安全代理;
hibernate框架,使用动态代理模式。CGLIB.jar
spring AOP 动态代理
3.享元模式
提高系统性能为目的的模式之一,避免对象的重复创建,提高数据的重用性,空间换时间的做法。
例子:获取员工信息。先从缓存中查找,没有,去数据库查询,然后放入到缓存。
4.装饰者模式
这是一个设计非常巧妙的结构,它可以动态添加对象的功能。在基本的设计原则中,有一条重要的设计准则:合成/聚合复用原则。根据该原则的思想,代码复用应该尽可能使用委托,而不是使用继承。应为继承是一种紧密的耦合,任何父类的改动都会影响其子类。而委托则是松耦合,只要接口不变,委托类的改动并不会影响其上层对象.装饰者模式就充分运用了这种思想,用过委托机制,复用系统中的各个组件,在运行时,可以将这些功能自检进行叠加,使其拥有所有组件的功能.而各个子功能模块,被很好的维护在各个组件的相关类中,拥有整洁的系统结构.jdk中 I/O流 OutputStream InputStream。通过装饰者增加功能,BufferedOutputStream
5.观察者模式
观察者Observer,被观察者Observable避免轮询监听状态。状态修改时,主动通知常用的优化组件和方法缓冲 buffer缓存对象池数据库连接池并行替换串行负载均衡 Neginx 反向代理时间换空间 (CPU运行节约内存)空间换时间 (缓存)
java代码优化
1.慎用异常
异常捕获,放在循环外面
2.使用局部变量
调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(stack)中,速度较快。其他变量,入静态变量、实例变量等,都在堆(heap)中创建,速度较慢。
3.一维数组替换二维数组
4.提取运算表达式
5.静态方法,替换实例方法
常用工具类方法,使用静态方法。因为在java中,由于实例方法需要维护一张类似虚拟函数表的结构,以实现多动态支持。与静态方法相比,实例方法调用需要更多的资源。
jvm调优
java虚拟机的内存模型:程序计数器;虚拟机栈;本地方法栈;java堆;方法区(永久区)
1.程序计数器
程序计数器(program counter register)是一块很小的内存空间。由于java是支持多线程的语言,当线程数量超过CPU数量时,线程之间根据时间片轮询抢夺CPU资源。为此,每一个线程都必须用一个独立的程序计数器,用来记录下一条要运行的指令。各个线程之间的计数器互补影响,独立工作;是一块私有的内存空间。
2.java虚拟机栈
java虚拟机栈也是线程私有的内存空间,它和java线程在同一时间创建,用来保存方法的局部变量、部分结果,并参与方法的调用和返回。
3.本地方法栈
和java虚拟机栈的功能很相似,java虚拟机栈用于管理java函数的调用,而本地方法栈用于管理本地方法的调用。本地方法并不是java实现的。在SUN的hot spot 虚拟机中,不区分本地方法栈和虚拟机栈。
4.java堆 heap
java堆是java运行时内存中最为重要的部分,几乎所有的对象和数组都是在堆中分配的。java堆分为新生代和老年代,新生代用于存放刚刚产生的对象和年轻的对象,如果对象一直没有被回收,生存的足够长,老年对象就会被移入老年代。新生对象有可进一步细分为eden / survivor space0 / survivor space1。Eden意思是伊甸园,即对象的出身地,大部分对象刚刚建立时,通常会存放在这里。s0和s1为survivor空间,直译为幸存者,也就是说存放其中的对象至少经历了一次垃圾回收,并得以幸存。如果在幸存区的对象到了指定年龄扔未被回收,则有机会进入老年代(tenured)
5.方法区
方法区也是jvm内存区非常重要的一块内存区域,与堆空间类似,它也是被jvm中所有线程共享的。方法区主要保存的信息是类的元数据。方法区中最为重要的是类的类型信息、常量池、域信息、方法信息。类型信息包括类的完整名称、父类的完整名称、类型修饰符和
类型的直接接口类表;常量池包括这个类方法、域等信息所引用的常量信息;域信息包括域名称、域类型和域修饰符;方法信息包括方法名称、返回类型、方法参数、方法修饰符、方法字节码、操作数栈和方法帧栈的局部变量区大小以及异常表。总之方法区保存的信息,大部分来自于class文件,是java应用程序运行必不可少的重要数据。在hot spot 中 方法去也称为永久区,是一块独立于java堆的内存空间。虽然叫做永久区,但是在永久区中的对象,同样也是可以被GC回收的。一是GC对永久常量池的回收(常量池的常量没有被应用,String.intern()方法加入常量池);二是永久区对类元数据的回收(动态代理创建对象)。
参数设置
-Xms128M 设置最小堆内存
jvm会试图将系统内存尽可能的限制在-Xms中。当内存实际使用量触及-Xms时,会出发Full GC。将-Xms和-Xmx设置相同,可减少GC次数。
-Xmx256M 设置最大堆内存
-Xmn256M 设置新生代
设置为整理堆空间的1/4到 1/3左右。设置一个较大的新生代会减小老年代的大小,这样系统性能和GC很大影响。
设置-Xmn等同于设置了相同的-XX:NewSize=256M和-XX:MaxNewSize=256M
-XX:PermSize=128M
初始持久代大小
-XX:MaxPermSize=128M
持久代最大值
持久代的大小直接觉得了系统可以支持多少了类定义和多少常量。一般设置为64M,建议不超过128M
-Xss1M 线程栈(表示每个线程拥有1MB的栈空间)
设置过大,则系统所能运行的线程数会下降
-XX:SurvivorRatio=2
设置新生代比例关系
-XX:SurvivorRatio=eden/s0=eden/s1
-XX:NewRatio=2
设置老年代和新生代的比例
-XX:NewRatio=老年代/新生代
总结
JVM调优的主要过程有:确定堆内存大小(-Xms、-Xmx);合理分配新生代和老年代(-XX:NewRatio、-Xmn、-XX:SurvivorRatatio);确定永久区大小(-XX:PermSize、-XX:MaxPermSize)、选择垃圾收集器、对垃圾收集器合理设置。禁用显示GC(-XX:+DisableExplicitGC),禁用类元数据回收(-Xnoclassgc),禁用类验证(-Xverify:none)等设置,来提升系统性能。
温馨提示
文章来源与网络,如有异议,请联系我删除!
以上是关于JAVA性能调优的主要内容,如果未能解决你的问题,请参考以下文章