top -b -n 1 |grep java|awk '{print "VIRT:"$5,"RES:"$6,"cpu:"$9"%","mem:"$10"%"}'
top -p 25603 -H printf 0x%x 25842 jstack 25603 | grep 0x64f2 cat /proc/interrupts
(1)CPU
(2)Memory
(3)IO
(4)Networkhtml
能够从如下几个方面监控CPU的信息:
(1)中断;
(2)上下文切换;
(3)可运行队列;
(4)CPU 利用率。java
free 命令linux
[root@server ~]# free total used free shared buffers cached Mem: 3266180 3250000 10000 0 201000 3002000 -/+ buffers/cache: 47000 3213000 Swap: 2048276 80160 1968116
这里的默认显示单位是 kb。ios
各项指标解释nginx
什么是buffer/cache?算法
page cache数组
page cache 主要用来做为文件系统上的文件数据的缓存来用,尤为是针对当进程对文件有 read/write 操做的时候。浏览器
若是你仔细想一想的话,做为能够映射文件到内存的系统调用:mmap是否是很天然的也应该用到 page cache?在当前的系统实现里,page cache 也被做为其它文件类型的缓存设备来用,因此事实上 page cache 也负责了大部分的块设备文件的缓存工做。缓存
buffer cache服务器
buffer cache 主要用来在系统对块设备进行读写的时候,对块进行数据缓存的系统来使用。这意味着某些对块的操做会使用 buffer cache 进行缓存,好比咱们在格式化文件系统的时候。
通常状况下两个缓存系统是一块儿配合使用的,好比当咱们对一个文件进行写操做的时候,page cache 的内容会被改变,而 buffer cache 则能够用来将 page 标记为不一样的缓冲区,并记录是哪个缓冲区被修改了。这样,内核在后续执行脏数据的回写(writeback)时,就不用将整个 page 写回,而只须要写回修改的部分便可。
在当前的内核中,page cache 是针对内存页的缓存,说白了就是,若是有内存是以page进行分配管理的,均可以使用page cache做为其缓存来管理使用。
固然,不是全部的内存都是以页(page)进行管理的,也有不少是针对块(block)进行管理的,这部份内存使用若是要用到 cache 功能,则都集中到 buffer cache中来使用。(从这个角度出发,是否是buffer cache更名叫作block cache更好?)然而,也不是全部块(block)都有固定长度,系统上块的长度主要是根据所使用的块设备决定的,而页长度在X86 上不管是 32位仍是 64位都是 4k。
3.2.1 进程内存统计
/proc/[pid]/status
经过/proc//status能够查看进程的内存使用状况,包括虚拟内存大小(VmSize),物理内存大小(VmRSS),数据段大小(VmData),栈的大小(VmStk),代码段的大小(VmExe),共享库的代码段大小(VmLib)等等。
Name: gedit /*进程的程序名*/ State: S (sleeping) /*进程的状态信息,具体参见http://blog.chinaunix.net/u2/73528/showart_1106510.html*/ Tgid: 9744 /*线程组号*/ Pid: 9744 /*进程pid*/ PPid: 7672 /*父进程的pid*/ TracerPid: 0 /*跟踪进程的pid*/ VmPeak: 60184 kB /*进程地址空间的大小*/ VmSize: 60180 kB /*进程虚拟地址空间的大小reserved_vm:进程在预留或特殊的内存间的物理页*/ VmLck: 0 kB /*进程已经锁住的物理内存的大小.锁住的物理内存不能交换到硬盘*/ VmHWM: 18020 kB /*文件内存映射和匿名内存映射的大小*/ VmRSS: 18020 kB /*应用程序正在使用的物理内存的大小,就是用ps命令的参数rss的值 (rss)*/ VmData: 12240 kB /*程序数据段的大小(所占虚拟内存的大小),存放初始化了的数据*/ VmStk: 84 kB /*进程在用户态的栈的大小*/ VmExe: 576 kB /*程序所拥有的可执行虚拟内存的大小,代码段,不包括任务使用的库 */ VmLib: 21072 kB /*被映像到任务的虚拟内存空间的库的大小*/ VmPTE: 56 kB /*该进程的全部页表的大小*/ Threads: 1 /*共享使用该信号描述符的任务的个数*/
java内存组成介绍:堆(Heap)和非堆(Non-heap)内存
按照官方的说法:“Java 虚拟机具备一个堆,堆是运行时数据区域,全部类实例和数组的内存均今后处分配。堆是在 Java 虚拟机启动时建立的。” “在JVM中堆以外的内存称为非堆内存(Non-heap memory)”。
能够看出JVM主要管理两种类型的内存:堆和非堆。
简单来讲堆就是Java代码可及的内存,是留给开发人员使用的;非堆就是JVM留给本身用的。
因此方法区、JVM内部处理或优化所需的内存(如JIT编译后的代码缓存)、每一个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法 的代码都在非堆内存中。
-XX:+UseConcMarkSweepGC -X:+CMSPermGenSweepingEnabled -X:+CMSClassUnloadingEnabled,若是不须要移除而Perm Generation空间不够,能够加大一点:-X:PermSize=256M -X:MaxPermSize=512M
1.方法区
也称”永久代” 、“非堆”,它用于存储虚拟机加载的类信息、常量、静态变量、是各个线程共享的内存区域。默认最小值为 16 MB,最大值为 64 MB,能够经过-XX: PermSize 和 -XX: MaxPermSize 参数限制方法区的大小。
运行时常量池:是方法区的一部分,Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译器生成的各类符号引用,这部份内容将在类加载后放到方法区的运行时常量池中。
2.虚拟机栈
描述的是java 方法执行的内存模型:每一个方法被执行的时候 都会建立一个“栈帧”用于存储局部变量表(包括参数)、操做栈、方法出口等信息。
每一个方法被调用到执行完的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。声明周期与线程相同,是线程私有的。
局部变量表存放了编译器可知的各类基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(引用指针,并不是对象自己),其中64位长度的long和double类型的数据会占用2个局部变量的空间,其他数据类型只占1个。
局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法须要在栈帧中分配多大的局部变量是彻底肯定的,在运行期间栈帧不会改变局部变量表的大小空间。
3.本地方法栈
与虚拟机栈基本相似,区别在于虚拟机栈为虚拟机执行的java方法服务,而本地方法栈则是为Native方法服务。
4.堆
也叫作java 堆、GC堆是java虚拟机所管理的内存中最大的一块内存区域,也是被各个线程共享的内存区域,在JVM启动时建立。
该内存区域存放了对象实例及数组(全部 new 的对象)。其大小经过 -Xms (最小值) 和 -Xmx (最大值) 参数设置,-Xms为 JVM 启动时申请的最小内存,默认为操做系统物理内存的 1/64 但小于 1G;
-Xmx 为 JVM 可申请的最大内存,默认为物理内存的1/4但小于 1G,默认当空余堆内存小于 40% 时,JVM 会增大 Heap 到 -Xmx 指定的大小,可经过 -XX:MinHeapFreeRation= 来指定这个比列;
当空余堆内存大于70%时,JVM 会减少 heap 的大小到 -Xms 指定的大小,可经过XX:MaxHeapFreeRation= 来指定这个比列,对于运行系统,为避免在运行时频繁调整 Heap 的大小,一般 -Xms 与 -Xmx 的值设成同样。
因为如今收集器都是采用分代收集算法,堆被划分为新生代和老年代。新生代主要存储新建立的对象和还没有进入老年代的对象。老年代存储通过屡次新生代GC(Minor GC)任然存活的对象。
5.程序计数器
是最小的一块内存区域,它的做用是当前线程所执行的字节码的行号指示器,在虚拟机的模型里,字节码解释器工做时就是经过改变这个计数器的值来选取下一条须要执行的字节码指令,分支、循环、异常处理、线程恢复等基础功能都须要依赖计数器完成。
直接内存并非虚拟机内存的一部分,也不是Java虚拟机规范中定义的内存区域。jdk1.4中新加入的NIO,引入了通道与缓冲区的IO方式,它能够调用Native方法直接分配堆外内存,这个堆外内存就是本机内存,不会影响到堆内存的大小。
查看 JVM 堆内存状况
jmap -heap [pid]
[root@server ~]$ jmap -heap 837 Attaching to process ID 837, please wait... Debugger attached successfully. Server compiler detected.J VM version is 24.71-b01 using thread-local object allocation. Parallel GC with 4 thread(s)//GC 方式Heap Configuration: //堆内存初始化配置Min HeapFreeRatio = 0 //对应jvm启动参数-XX:MinHeapFreeRatio设置JVM堆最小空闲比率(default 40) MaxHeapFreeRatio = 100 //对应jvm启动参数 -XX:MaxHeapFreeRatio设置JVM堆最大空闲比率(default 70) MaxHeapSize = 2082471936 (1986.0MB) //对应jvm启动参数-XX:MaxHeapSize=设置JVM堆的最大大小 NewSize = 1310720 (1.25MB)//对应jvm启动参数-XX:NewSize=设置JVM堆的‘新生代’的默认大小 MaxNewSize = 17592186044415 MB//对应jvm启动参数-XX:MaxNewSize=设置JVM堆的‘新生代’的最大大小 OldSize = 5439488 (5.1875MB)//对应jvm启动参数-XX:OldSize=<value>:设置JVM堆的‘老生代’的大小NewRatio = 2 //对应jvm启动参数-XX:NewRatio=:‘新生代’和‘老生代’的大小比率 SurvivorRatio = 8 //对应jvm启动参数-XX:SurvivorRatio=设置年轻代中Eden区与Survivor区的大小比值 PermSize = 21757952 (20.75MB) //对应jvm启动参数-XX:PermSize=<value>:设置JVM堆的‘永生代’的初始大小 MaxPermSize = 85983232 (82.0MB)//对应jvm启动参数-XX:MaxPermSize=<value>:设置JVM堆的‘永生代’的最大大小 G1HeapRegionSize = 0 (0.0MB) Heap Usage://堆内存使用状况 PS Young Generation Eden Space://Eden区内存分布 capacity = 33030144 (31.5MB)//Eden区总容量 used = 1524040 (1.4534378051757812MB) //Eden区已使用 free = 31506104 (30.04656219482422MB) //Eden区剩余容量 4.614088270399305% used //Eden区使用比率 From Space: //其中一个Survivor区的内存分布 capacity = 5242880 (5.0MB) used = 0 (0.0MB) free = 5242880 (5.0MB) 0.0% used To Space: //另外一个Survivor区的内存分布 capacity = 5242880 (5.0MB) used = 0 (0.0MB) free = 5242880 (5.0MB) 0.0% used PS Old Generation //当前的Old区内存分布 capacity = 86507520 (82.5MB) used = 0 (0.0MB) free = 86507520 (82.5MB) 0.0% used PS Perm Generation//当前的 “永生代” 内存分布 capacity = 22020096 (21.0MB) used = 2496528 (2.3808746337890625MB) free = 19523568 (18.619125366210938MB) 11.337498256138392% used 670 interned Strings occupying 43720 bytes.
关于这里的几个generation网上资料一大把就不细说了,这里算一下求和能够得知前者总共给Java环境分配了644M的内存,而ps输出的VSZ和RSS分别是7.4G和2.9G,这究竟是怎么回事呢?
前面jmap输出的内容里,MaxHeapSize 是在命令行上配的,-Xmx4096m,这个java程序能够用到的最大堆内存。
VSZ是指已分配的线性空间大小,这个大小一般并不等于程序实际用到的内存大小,产生这个的可能性不少,好比内存映射,共享的动态库,或者向系统申请了更多的堆,都会扩展线性空间大小,要查看一个进程有哪些内存映射,可使用 pmap 命令来查看:
pmap -x [pid]
[root@server ~]$ pmap -x 837 837: java Address Kbytes RSS Dirty Mode Mapping 0000000040000000 36 4 0 r-x-- java 0000000040108000 8 8 8 rwx-- java 00000000418c9000 13676 13676 13676 rwx-- [ anon ] 00000006fae00000 83968 83968 83968 rwx-- [ anon ] 0000000700000000 527168 451636 451636 rwx-- [ anon ] 00000007202d0000 127040 0 0 ----- [ anon ] ... ... 00007f55ee124000 4 4 0 r-xs- az.png 00007fff017ff000 4 4 0 r-x-- [ anon ] ffffffffff600000 4 0 0 r-x-- [ anon ] ---------------- ------ ------ ------ total kB 7796020 3037264 3023928
这里能够看到不少anon,这些表示这块内存是由mmap分配的。
RSZ是Resident Set Size,常驻内存大小,即进程实际占用的物理内存大小, 在如今这个例子当中,RSZ和实际堆内存占用差了2.3G,这2.3G的内存组成分别为:
jstat -gcutil [pid]
[root@server ~]$ jstat -gcutil 837 1000 20 S0 S1 E O P YGC YGCT FGC FGCT GCT 0.00 80.43 24.62 87.44 98.29 7101 119.652 40 19.719 139.371 0.00 80.43 33.14 87.44 98.29 7101 119.652 40 19.719 139.371
分析 JVM 堆内存中的对象
#查看存活的对象统计 jmap -histo:live [pid] #dump 内存 jmap -dump:format=b,file=heapDump [pid] #而后用jhat命令能够参看 jhat -port 5000 heapDump
在浏览器中访问:http://localhost:5000/ 查看详细信息
响应时间是指系统对请求做出响应的时间。直观上看,这个指标与人对软件性能的主观感觉是很是一致的,由于它完整地记录了整个计算机系统处理请求的时间。
因为一个系统一般会提供许多功能,而不一样功能的处理逻辑也千差万别,于是不一样功能的响应时间也不尽相同,甚至同一功能在不一样输入数据的状况下响应时间也不相同。
因此,在讨论一个系统的响应时间时,人们一般是指该系统全部功能的平均时间或者全部功能的最大响应时间。
固然,每每也须要对每一个或每组功能讨论其平均响应时间和最大响应时间。
对于单机的没有并发操做的应用系统而言,人们广泛认为响应时间是一个合理且准确的性能指标。须要指出的是,响应时间的绝对值并不能直接反映软件的性能的高低,软件性能的高低实际上取决于用户对该响应时间的接受程度。
对于一个游戏软件来讲,响应时间小于100毫秒应该是不错的,响应时间在1秒左右可能属于勉强能够接受,若是响应时间达到3秒就彻底难以接受了。
而对于编译系统来讲,完整编译一个较大规模软件的源代码可能须要几十分钟甚至更长时间,但这些响应时间对于用户来讲都是能够接受的。
吞吐量是指系统在单位时间内处理请求的数量。对于无并发的应用系统而言,吞吐量与响应时间成严格的反比关系,实际上此时吞吐量就是响应时间的倒数。
前面已经说过,对于单用户的系统,响应时间(或者系统响应时间和应用延迟时间)能够很好地度量系统的性能,但对于并发系统,一般须要用吞吐量做为性能指标。
对于一个多用户的系统,若是只有一个用户使用时系统的平均响应时间是t,当有你n个用户使用时,每一个用户看到的响应时间一般并非n×t,而每每比n×t小不少(固然,在某些特殊状况下也可能比n×t大,甚至大不少)。
这是由于处理每一个请求须要用到不少资源,因为每一个请求的处理过程当中有许多不走难以并发执行,这致使在具体的一个时间点,所占资源每每并很少。也就是说在处理单个请求时,在每一个时间点均可能有许多资源被闲置,当处理多个请求时,若是资源配置合理,每一个用户看到的平均响应时间并不随用户数的增长而线性增长。
实际上,不一样系统的平均响应时间随用户数增长而增加的速度也不大相同,这也是采用吞吐量来度量并发系统的性能的主要缘由。
通常而言,吞吐量是一个比较通用的指标,两个具备不一样用户数和用户使用模式的系统,若是其最大吞吐量基本一致,则能够判断两个系统的处理能力基本一致。
并发用户数是指系统能够同时承载的正常使用系统功能的用户的数量。与吞吐量相比,并发用户数是一个更直观但也更笼统的性能指标。
实际上,并发用户数是一个很是不许确的指标,由于用户不一样的使用模式会致使不一样用户在单位时间发出不一样数量的请求。
一网站系统为例,假设用户只有注册后才能使用,但注册用户并非每时每刻都在使用该网站,所以具体一个时刻只有部分注册用户同时在线,在线用户就在浏览网站时会花不少时间阅读网站上的信息,于是具体一个时刻只有部分在线用户同时向系统发出请求。
这样,对于网站系统咱们会有三个关于用户数的统计数字:注册用户数、在线用户数和同时发请求用户数。因为注册用户可能长时间不登录网站,使用注册用户数做为性能指标会形成很大的偏差。而在线用户数和同事发请求用户数均可以做为性能指标。
相比而言,以在线用户做为性能指标更直观些,而以同时发请求用户数做为性能指标更准确些。
每秒查询率QPS是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准,在因特网上,做为域名系统服务器的机器的性能常常用每秒查询率来衡量。对应fetches/sec,即每秒的响应请求数,也便是最大吞吐能力。
从以上概念来看吞吐量和响应时间是衡量系统性能的重要指标,QPS虽然和吞吐量的计量单位不一样,但应该是成正比的,任何一个指标均可以含量服务器的并行处理能力。固然Throughput更关心数据量,QPS更关心处理笔数。
CPU Load Average < CPU个数 核数 0.7
Context Switch Rate
就是Process(Thread)的切换,若是切换过多,会让CPU忙于切换,也会致使影响吞吐量。
《高性能服务器架构 》这篇文章的第2节就是说的是这个问题的。
究竟多少算合适?google 了一大圈,没有一个确切的解释。
Context Switch大致上由两个部分组成:中断和进程(包括线程)切换,一次中断(Interrupt)会引发一次切换,进程(线程)的建立、激活之类的也会引发一次切换。CS的值也和TPS(Transaction Per Second)相关的,假设每次调用会引发N次CS,那么就能够得出
Context Switch Rate = Interrupt Rate + TPS* N
CSR减掉IR,就是进程/线程的切换,假如主进程收到请求交给线程处理,线程处理完毕归还给主进程,这里就是2次切换。
也能够用CSR、IR、TPS的值代入公式中,得出每次事物致使的切换数。所以,要下降CSR,就必须在每一个TPS引发的切换上下功夫,只有N这个值降下去,CSR就能下降,理想状况下N=0,可是不管如何若是N >= 4,则要好好检查检查。另外网上说的CSR<5000,我认为标准不应如此单一。
这三个指标在 LoadRunner 中能够监控到;另外,在 linux 中,也能够用 vmstat 查看r(Load Arerage),in(Interrupt)和cs(Context Switch)
uptime
dmesg
top
查看进程活动状态以及一些系统情况
vmstat
查看系统状态、硬件和系统信息等
iostat
查看CPU 负载,硬盘情况
sar
综合工具,查看系统情况
mpstat
查看多处理器情况
netstat
查看网络情况
iptraf
实时网络情况监测
tcpdump
抓取网络数据包,详细分析
mpstat
查看多处理器情况
tcptrace
数据包分析工具
netperf
网络带宽工具
dstat
综合工具,综合了 vmstat, iostat, ifstat, netstat 等多个信息
转载自 Zane Blog,原文为《服务调优》