Java性能调优(二):IO和内存分析

文件IO消耗分析

Linux在操作文件的时候,先将文件放入文件缓存,直到内存不足或者进程使用。这是一种提升IO速度的方式。

1.pidstat

        

KB_rd/s表示每秒读,KB_wr/s每秒写

2.iostat

查看历史IO

网络IO分析

使用命令 sar -n FULL 1 2

内存消耗分析

JVM内存消耗过多会导致GC喜欢 ii 次难过频繁,CPU消耗增加,应用线程的执行速度严重下降,甚至造成OutOfMemoryError,最终导致Java进程退出。

vmstat

可使用这个命令查看信息和内存相关的主要是memory下的swpd、free、buff、cache以及swap下的si和so。

swpd:虚拟内存已使用的部分

free:空闲的物理内存

buff:用于缓冲的内存

cache:缓存的内存

swap的si:每秒从disk读至内存的数据量

swap的so:每秒从内存中xierudisk的数据量。

swap过高通常是由于物理内存不够用,swap消耗情况主要关注的是swap IO的状况。

Java应用是单进程应用,因此只要JVM的内存设置不是过大,是不会操作到swap区域的。

sar

物理内存相关的信息主要是kbmemfree、kbmemused、%memused、kbbuffers、kbcached。当物理内存有空心啊时,linux会使用一些物理内存用于buffer 以及cache。一提升系统的运行效率;物理内存=kbmemfree+kbbuffers+kbcahched。

vmstat和sar的共同弱点是不能分析进程所占用的内存量。

top

可查看进程所消耗的内存量,看到的是JVM已分配的内存已加上Java应用所消耗的JM以外的物理内存,这会导致top中看到Java所消耗的内存带下可能超过-Xmx机上-XX:MaxPerSize设置内存大小,并且Java程序启动后知识占据-Xms的地址空间,但并没有占据实际的内存,只有在相应的地址空间被使用过后被计入消耗的内存中。很难根据top判断Java进程消耗的内存中有多少是属于JVM,一个小技巧是,对犹豫内存满而发生过Full GC的应用而言,多数情况先,可以认为java进程中显示出来的内存消耗值即为JVM -Xmx的值加上消耗的JVM外的内存值。

pidstat

使用命令 pidstat -r -p pid interval, [times]. 执行命令可查看该进程所占用的物理内存和虚拟内存大小。

对物理内存的消耗

基于Direct BytBuffer可以很容易地实现对物理内存的直接操作,无须耗费JVM Heap区。

package cn.edu.hust;

import java.nio.ByteBuffer;

public class JVM1 {
    public static void main(String[] args) throws InterruptedException {
        Thread.sleep(20000);
        System.out.println("read to create bytes, so JVM heap will be used");
        byte[] bytes=new byte[128*1000*1000];
        bytes[0]=1;
        bytes[1]=2;
        Thread.sleep(10000);
        System.out.println("read to allocate & put direct bytebuffers,no JVM heap should be used");

        ByteBuffer buffer=ByteBuffer.allocate(128*1024*1024);
        buffer.put(bytes);
        buffer.flip();
        Thread.sleep(10000);

        System.out.println("ready to gc,JVM heap will be freed");
        bytes=null;
        System.gc();
        Thread.sleep(10000);
        System.out.println("ready to get bytes,then JVM heap will be used");

        byte[] resultBytes=new byte[128*1000*1000];
        buffer.get(resultBytes);
        System.out.println("resultBytes[1] is:"+resultBytes[1]);
        Thread.sleep(10000);
        System.out.println("ready to gc all");
        buffer=null;
        resultBytes=null;
        System.gc();
        Thread.sleep(10000);
    }
}


在IDEA中配置 -Xms140M -Xmx140M参数执行上面的代码可以根据命令查看

基于direct vytebuffer消耗的JVM heap外的物理内存,同样是给予GC方式释放。

对JVM内存的消耗

Java程序出现内存消耗过多、GC频繁或者OutOfmemeroyError情况,要首先分析其耗费的JVM外的物理内存还是JVM heap区。

猜你喜欢

转载自blog.csdn.net/oeljeklaus/article/details/80666433