Chapter8-面向性能的软件构造方法

目录

      • 目录
        • 8.1、Metrics,Princple,and Methods of Construction for Performance
          • 8.1.1、Performance Metrics(性能度量指标)
          • 8.1.2、Memory Performance(存储性能)
            • 8.1.2.1、Three modes of object management
            • 8.1.2.2、Java Memory Model
            • 8.1.2.3、Garbage Collection
            • 8.1.2.3.1、Garbage Collection Terminology(GC相关术语)
            • # 8.1.2.3.2、Definition of Garbage Collection(垃圾回收的定义)
            • # 8.1.2.3.3、Basic Algorithms: Reference Counting, MarkSweep,Mark-Compact, and Copying(四种基本算法)
            • # 8.1.2.3.4、Garbage Collection in JVM
            • # 8.1.2.3.5、Garbage Collection Tuning in JVM
          • 8.1.3、Algorithm Performance(算法性能)
          • 8.1.4、I/O Performance(I/O性能)
        • 8.2、Dynamic Program Analysis Methods and Tools
        • 8.3、Code Tuning for Performance Optimization

Chapter 8: Software Construction for Performance
第八章主要讲时空性能质量指标
内存管理模型:堆、栈
GC,root、reachable、unreachable、live、dead
GC的四种基本算法
Java/JVM的内存管理模型:各区域、各区域的GC方法
JVM GC性能调优:参数配置、GC模式选择
Java性能调优工具:jstat, jmap,jhat, Visual VM, MAT
Memory dump
Stack trace
Java代码调优的设计模式:singleton, prototype/cloneable,flyweight, object pool
String constant pool
常见的Java I/O方法

8.1、Metrics,Princple,and Methods of Construction for Performance

第一节主要讲时空性能的指标,以及一些提高性能的方法

8.1.1、Performance Metrics(性能度量指标)
运行时程序性能 Time performance(时间性能) Space performance(空间性能)
细节 ①Execution time:每条指令、每个控制结构、整个程序的执行时间;②Distribution of execution time:不同语句或控制结构执行时间的分布情况;③Time battleneck(时间瓶颈) ①Memory consumption:每个变量、每个复杂结构、整个程序的内存消耗;②Distribution of memory consumption:不同变量、数据结构的相对消耗;③Space bottleneck(空间瓶颈)④Evolution of memory consumption(内存随时间的变化)
影响运行性能的因素 ①Algorithm(算法);②Data structure(数据结构);③Memory allocation(内存分配);④Garbage collection(垃圾回收) ①Basic statements(基本语句);②Algorithm(算法);③Data structure(数据结构);④I/O(file,database,network communication,etc);⑤Concurrency / multi-thread / lock(并行、多线程、锁)
Code 得到执行时间:long time = System.currentTimeMillis(),elapsedTime = stopTime - startTime 得到内存消耗:Runtime runtime = Runtime.getRuntime(),runtime.gc(),long memory = runtime.totalMemory() - runtime.freeMemory()
8.1.2、Memory Performance(存储性能)
8.1.2.1、Three modes of object management

主要介绍三种基本的内存分配模型
差异在于:如何何时程序对象内存对象之间建立联系

Memory Allocation Static allocation(静态分配) Dynamic allocation(动态分配)
Define 静态内存分配,在编译阶段就已经确定好了内存分配 在运行时动态分配内存,建立新的内存对象(基于堆和栈的内存管理都是动态分配)
Three Modes Static Stack-based Heap-based
Details 在将程序load进内存的时候或开始执行的时候,确定所有对象的分配;不支持递归,不支持动态创建的可变长的复杂数据类型 栈存储方法调用以及方法执行中的局部数据;后进先出,无法支持复杂数据类型 在一块内存里分为多个小块,每块包含一个对象,或者未被占用自;代码中的一个变量可以在不同时间被关联到不同的内存对象上,无法在编译阶段确定,同时内存对象也可以进一步指向其他对象;自由模式的内存管理,动态分配,可管理复杂的动态数据结构
About 某些对象延续的时间比创建它的方法所延续的时间更长(因为方法返回后,栈清空,所以stack不行);递归的数据结构,长度可变的数据结构(所以静态方法和stack都不行);经常要使用不限定长度的数据结构(用堆进行管理)
Space reclamation(内存回收) 在静态内存分配模式下,无需进行内存回收:所有都是已确定的 在栈上进行内存空间回收:按block(某个方法)整体进行 在heap上进行内存空间回收,最复杂,无法提前预知某个object是否已经变得无用(在GC中将详情讲解)

图解基于的分配模型
(注意方法参数时通过栈传递的)
Chapter8-面向性能的软件构造方法_第1张图片
图解基于的分配模型
Chapter8-面向性能的软件构造方法_第2张图片

8.1.2.2、Java Memory Model

主要介绍java中的内存分配模型,java通过JVM(java虚拟机)进行基于堆和栈的管理内存

Thread stack Heap
每个运行在JVM中的线程都有自己的线程栈,管理其局部数据,各栈之间彼此不可见;所有局部的基本数据类型都在栈上创建;多线程之间传递数据,是通过赋值而非引用 所有的对象(Object,eg. Byte,Integer,Long)都在堆上创建;即使是局部变量的object,也是在堆上创建;堆上创建的对象可被所有线程共享引用;如果两个线程调用同一个对象上的某个方法,他们分别保留该方法的局部变量的拷贝
①基本数据类型的局部变量;②指向一个对象的局部变量;③一个对象可能包含方法,这些方法包含局部变量,这些局部变量存储在线程栈上; ①所有对象(object)存储在堆上;②对象的基本类型成员变量也存储在堆上;③如果一个成员变量是指向一个对象的指针,这个成员变量存储在堆上;④静态类变量存储在堆上
8.1.2.3、Garbage Collection

考点:
GC,root、reachable、unreachable、live、dead
GC的四种基本算法

8.1.2.3.1、Garbage Collection Terminology(GC相关术语)

对象之间的引用关系构成一个有向图:
- 图的活动对象是可从根访问的对象。
- 执行计算的进程称为改变器(mutator),因为它被视为动态地改变对象图。

root(根对象) reachable(可达对象) unreachable(不可达对象) live(活对象) dead(死对象)
在系统执行期间的任何时刻,根的集合由以下对象组成:①系统的根对象 ②附加到本地实体的任何对象或当前正在执行的例程的正式参数(包括函数的本地实体结果) 根据对象的”活性”有无区分;根对象的所有孩子节点,直接或间接都是可到达的,其他任何对象都是不可达的 从root可达 从root不可达(需要注意的是,死对象可能存在其他对象的引用)
内存回收的首要问题是将可达对象与不可达对象分离开来
# 8.1.2.3.2、Definition of Garbage Collection(垃圾回收的定义)

垃圾回收器根据对象的”活性“(从root的可达性)来决定是否回收该对象的内存,”“的对象就是需要回收的”垃圾”。
垃圾回收GC:识别垃圾“对象,把其占用内存加以回收
分为手动回收和自动回收两种方式。

手动回收有以下几种方法:
①Defensive Programming(防御式编程):复制对象,而非引用;在局部回收内存;浪费空间但是有用;
②Pairing Principle(配对原则):使用new()创建,对应的使用delete()删除;
③Ownership Concept(所有权概念);
④Monitoring Technique(检测技术):使用Malloc()Free()
⑤Administrator technique (管理员技术)。

下面介绍自动回收GC方法:

# 8.1.2.3.3、Basic Algorithms: Reference Counting, MarkSweep,Mark-Compact, and Copying(四种基本算法)
类别 Reference Counting(引用计数) MarkSweep(标记-清除) Mark-Compact(标记-整理,介绍较少) Copying(复制)
基本思想 为每个object存储一个计数RC,当有其他reference指向它时,RC++;当有其他reference与其断开时,RC–;如果RC==0,则回收它 为每个object设定状态位(live/dead)并记录,即mark阶段;将标记为dead的对象进行清理,即sweep阶段 首先标记每个object(使用mark-sweep的mark阶段),然后将所有标记为live的移到后面,最后将前面所有dead对象回收 首先将堆分为Fromspace和Tospace两部分,然后在Tospace中为对象分配内存,当Tospace满时,将其中所有活对象复制到Fromspace中,回收Tospace中所有死对象,周期进行
注意点 递归释放:一旦对象的RC = 0,它就可以被释放。 但对象可能包含对其他对象的引用,在这个对象被释放之前,其引用的对象的RC应该改变。 周期性进行mark,sweep,其中mark位置为对象首位(称为mark-bit)即可 类似mark-sweep,多了整理操作,让之后堆使用更方便 该GC策略与mark-compact的区别在于:不是在同一个区域内进行整 理,而是将live对象全部复制到另一个区域。
优点 简单、计算代价分散,“幽灵时间”短->0(一旦没有了引用,立即回收) 全面:循环收集垃圾;在指针操作上没有运行时间开销;与mutator松耦合;不移动对象, 不会破坏任何mutator不变量,优化器友好,只需要引用每个要发现的活对象(而不需要找到每个引用) 免费压缩;所有对象大小的分配非常简单 ,空间检查是指针比较 ,只需增加空闲指针分配;只处理活对象(通常是堆的一小部分);固定的空间开销 - 释放和扫描指针 - 转发地址可以写在用户数据上;全面:循环收集垃圾;简单实现合理高效的复制GC
缺点 不全面(容易漏掉循环引用的数据)、要持续不断的计算(代价高)、难以支持并发、等 停止/开始会导致的停顿和漫长的僵尸时间(开始要遍历所有对象);复杂性是O(heap)而不是O(live) ,在标记阶段访问每个活对象 ,所有活和死对象都在sweep阶段被访问;如果堆已满(经常发生),则需要Mark阶段需要大量标记;碎片和标记堆栈溢出是问题;跟踪收集器必须能够找到根对象(与引用计数不同) 停止和复制开销较大;对象的位置周期性改变;需要其他简单收集器两倍的地址空间;复制大型对象的成本;长期数据可能被重复复制;必须更新所有引用;移动对象可能会破坏mutator不变量;广度优先复制可能会干扰局部模式
# 8.1.2.3.4、Garbage Collection in JVM

考点:Java/JVM的内存管理模型:各区域、各区域的GC方法
Java GC将堆分为不同的区域,各区域采用不同的GC策略,以提高GC的效率
针对不同的区域,使用不同的GC策略
Chapter8-面向性能的软件构造方法_第3张图片

Young Generation(年轻代) Old Generation(年老代) Pernament Generation(永久代)
Eden S0(From) S1(To) Old Perm
java分配的对象在eden创建 对象存活空间,YGC后从Eden转移到该处 minorGC从Young转移到该处 保存VM和Java元数据比如Strings和类静态变量
只有一小部分对象可较长时间存活,故采用copy算法减少GC代价,具体就是在S0和S1之间相互拷贝;当没有足够空间时,使用minor GC进行垃圾收集;如果经过多次minor GC仍存活,将其copy到old generation 这里的对象有很高的幸存度,使用Mark-Sweep或Mark-Compact算法;当没有足够空间时(Old generation满,意味无法进行下一次minor GC),启动full GC 当perm generation满了之后,无法存储更多的元数据,也启动full GC

minor GC和f**ull GC**是独立进行的,减少代价;
minor GC仅发生在young generation
只有当某个区域不能再为对象分配内存时(满),才启动GC。

# 8.1.2.3.5、Garbage Collection Tuning in JVM

考点:JVM GC性能调优:参数配置、GC模式选择
调整JVM的垃圾回收的特点
①尽可能减少GC时间,一般不超过**程序执行时间的**5%
②一旦初始分配给程序的内存满了,就抛出内存溢出异常(OutOfMemoryError)
③在启动程序时,可为其配置内存分配*的具体大小*

调整JVM的垃圾回收的方法
确定堆的大小
堆的大小决定着VM将会以何种频度进行GC每次GC时间多长;这两个指标具体取值多少为“优”,需要针对特定应用进行分析; 较大的heap会导致较少发生GC,但每次GC**时间很长;如果根据程序需要来设置内存需要的heap大小,则需要频繁GC**,但每次GC的时间较短
初始和最大的heap尺寸

Java -Xms 1024M -Xmx 2048M

heap尺寸可随时间变化,heap尺寸变化时需要full GC
具体设置
Chapter8-面向性能的软件构造方法_第4张图片
Chapter8-面向性能的软件构造方法_第5张图片
选择GC模式
Chapter8-面向性能的软件构造方法_第6张图片
使用verbose GC查看详细信息以确定堆的大小
eclipse->Run->Run Configuration->Arguments->VM arguments

-server -Xms1024m -Xmx1024m -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:gc.log

-verbose:gc是必须写的,-Xms1024m为heap**初始值-Xmx1024m为heap最大值,-XX:+PrintGCDetails打印GC具体信息,-Xloggc:gc.log将GC信息保存到日志**gc.log中
得到的数据中如下,其中Allocated Failed即为minor GCFull GC时间应小于3-5s
Chapter8-面向性能的软件构造方法_第7张图片

自动记录内存将要不足的情况
手工请求GC
请求线程栈

8.1.3、Algorithm Performance(算法性能)

详情:《算法导论》

8.1.4、I/O Performance(I/O性能)

I/O of software system
Java I/O APIs
Chapter8-面向性能的软件构造方法_第8张图片
Java nio APIs
Chapter8-面向性能的软件构造方法_第9张图片
详情参考:javadoc

8.2、Dynamic Program Analysis Methods and Tools

本节,介绍如何利用工具对运行的程序性能进行动态监控,以发现性能瓶颈,并试图加以消除
考点:
Java性能调优工具:jstat, jmap,jhat, Visual VM, MAT
Memory dump
Stack trace



































命令行分析工具 JConsole Visual VM Memory Analyzer(MAT)
jhat jmap jstat jstack JConsole Visual VM MAT
导出heap dump,浏览、查询其中的对象分布情况 输出内存中的对象分布情况 获取JVM的heap使用和GC的性能统计数据 获取java数据的stack trace
获取heap dump的方法:在运行时使用jmap -dump,jconsole,hprof工具;jhat filenam在http://127.0.0.1:7000浏览和查询(使用OQL语言)heap dump 使用jmap -dump:format=b,file=filename导出heap dump;jamp -heap得到heap的GC信息、堆配置、堆消耗总结;jmap -permstat得到permanent generation的数据分析 使用jstat -gcutil输出heap个区域的占用情况 使用jsp得到程序的pid,然后使用jstack得到程序运行时栈情况(– 定位线程出现长时间停顿的原因,如多线程间死锁、死循环、请求外部资源导致的长时间等待等。) GUI monitoring tool 用法较多 同样用来分析heap dump

8.3、Code Tuning for Performance Optimization

考点
Java代码调优的设计模式:singleton, prototype/cloneable,flyweight, object pool(下节分析)
String constant pool(字符串常量池)
常见的Java I/O方法

你可能感兴趣的:(SC)