四、性能分析-硬件内存
内存:
程序代码、网络数据,外部数据进入cpu的桥梁,内存的速度,要比cpu的速度慢,磁盘更慢
内存知识:
1. 当打开一个软件,就会分配虚拟内存、物理内存空间,cpu读取虚拟内存;
2. 程序在启动时,并不会把所有的数据,加到内存
3. 32位的系统,最大支持的内存条,只有4g,64位系统,最大可以支持128T
4. 程序在启动时,会有一个内存配置信息,就会告诉系统,我要在整改内存条中,申请多少m内存空间。
内存中,内存地址与存储单元组成的:存储单元中,就是来真正存储内容,不同的数据类型,存储单元大小不一样(int float, char)
数据结构:
链表:每一个数据,它都存储了下一个数据的地址(内存地址),在插入数据的时候,我可以把数据放在任何位置
每一个数据,都有自己的地址 + 数据 +下一个数据的地址
插入数据时, 数据本身可以在内存空间的任意位置,然后,在插入数据的位置前一个数据改变下一个数据地址,指向我的这位置,我的数据位置记录的下一个位置......
这种数据插入方式,速度要比列表要块
但是,读取某个数据的速度降低,因为我们每查询一个数据,都要从链表的第1个数据开始查找,一直到找到为止,这个中间,我们可能要进行大量IO数据交互
列表:往列表中插入数据,插入点之后的数据,全部都需要移动,这个插入速度比较慢
二叉树:它也链表
插入数据时,数据进行比较,比数据小的在左边,比数据大的插入在右边
查找数据时,比数据大的,我就去右边找,比数据小,我就去左边找,这个时候,IO就比链表要少很多。
数据类型:
栈stack: 存储的数据比较小,比如某个变量
LIFO 后进先出
压入 push
队列: FIFO 排队 先进先出
顺序队列,
循环队列
堆heap: 存储的数据比较复杂
对象
一个程序: 如: 这个程序启动要 256m
先有一个虚拟内存地址 + 物理内存地址
虚拟内存地址: 记录物理内存中存储了哪些数据,在什么地方
内存使用:
一个程序(内存)运行起来,需要分配一个内存空间(可大可小),无异常时就在分配的空间中弹性伸缩存储(内存空间包含一块栈区和一块堆区,还包括其他的)
栈区:存放程序中变量;变量有一定的作用域,离开作用域,空间就会被释放,所以更新速度快,生命周期短
堆区:存放程序中对象,凡是new出来的都存放在堆里,若数据消失,实体不会马上释放
JVM(Java虚拟机):将Java代码转义成机器认识的字节码
其他区:程序计数器、java虚拟机栈、本地方法栈、方法区、堆内存
程序计数器:记录程序执行字节码的行号指示器
java虚拟机栈:Java方法直销的行号指示器
方法区:共享内存区域,存储已被虚拟机加载的数据
内存泄漏:内存的资源不及时释放,一直占用,导致可用的内存资源越来越少。
内存溢出:内存泄漏到一定的时间,可用的空间就会越来越少,某一次我要用比较大的空间时,发现,我申请不到足够的空间了,我申请的空间已经超过最大可用空间,内存溢出。
内存溢出查看方法:1、内存溢出,在错误日志,会出现;2、jmap,3、arthas
top: 进程列表中有3列, 虚拟内存、物理内存、共享内存
堆内存:新生代、老年代、永久代(元空间)
新生代new:昙花一现,朝生夕死的对,如:你写的代码,方法里面变量; 新生代数据,经过copy算法,如copy了15次,还存在就移到老年代
老年代Tenured:大对象或多次被GC后还存在的对象
永久代Perm:类信息、常量、静态变量
GC资源回收:
1.YGC:Young Generation(Minor GC):针对新生代的Eden区资源回收
FGC:(Major GC):处理的区域同时包含新生代和老年代
资源回收的时候,都会出现卡顿,YGC的卡断时间会比较短,FGC卡顿的时间会比较长
2.先确定哪些资源是可以被回收
判断资源是否已死:引用实数法,可达性算法
3.什么时候回收
分配空间不足
定时回收
4.资源回收方式
新生代:copy算法
老年代:标记整理法
5.性能测试中,就对于这个gc是要关注(堆栈比例配置)
1.如果 新生代资源分配过多,那么,老年代这变就要少, 老年代的空间,我可能就要经常的进行FGC, FGC频率高了,那么累计的gc的时间就长,导致性能比较差
2.如果 新生代分配的资源少了,那么老年代就分配多些,我的新生代的资源回收频率YGC就要高, 那么累计的ygc的时间也可能长,我的性能也可能较差
-XX:SurivivorRatio=8 eden空间、from空间、to空间的比例 8:1:1
-XX:MaxMetaspaceSize jdk1.7 jdk1.8这个元空间参数配置名称变了
- 查看内存:
- free -h
top E/e 切换单位
- free -h
实例: