week9 性能优化(三)作业和学习总结
作业一:
(至少完成一个)
请简述 JVM 垃圾回收原理。
JVM 垃圾回收即使将 JVM 堆中的已经不再被使用的对象清理掉,释放宝贵的内存资源。
JVM 通过一种可达性分析算法进行垃圾对象的标识。具体过程是:
从线程栈帧中的局部变量,或者方法区的静态变量出发,将这个变量引用的对象进行标记;
然后看这些被标记的对象是否引用了其它对象,继续进行标记;
所有被标记过的对象都是被使用的对象,而那些没有被标记的对象就是可回收的垃圾对象了。
进行完标记以后,JVM 就会对垃圾对象占用的内存进行回收,回收主要有三种方法:
清理:将垃圾对象占据的内存清理掉,其实 JVM 并不会真的将这些垃圾内存进行清理,而是将这些垃圾对象占用的内存空间标记为空闲,记录在一个空闲的列表里,当应用程序需要创建新的对象的时候,就从空闲列表中找一段空闲内存分配给这个对象。
压缩:从堆空间的头部开始,将存活的对象拷贝到一段连续的内存空间中,那么其余的空间就是连续的空闲空间。
复制:将堆空间分成两部分,只在其中一部分创建对象,当这个部分空间用完的时候,将标记过的可用对象复制到另一个空间中。
清理:把已经没用的空间标记为可用空间。
压缩:清理有个短板,空间不是连续的,压缩就是把还在用的 copy 放在前面。
复制:压缩还是需要成本的,速度较慢;分两块区域会更好一点。
JVM 分代垃圾回收
创建新对象在 Eden 区,当 Eden 区满了以后,就会进行 Young GC,把在用的对象 copy 到 From 区;
当 Eden 区再次满了以后,再次进行 YoungGC,把 Eden 区和 From 区的在用对象,copy 到 To 区;
当多次 Eden 发送 YoungGC,把一些还用的对象放到老年代;
当老年代满了以后,就会进行 Full GC。这是要应用线程都要暂停,进行 Full GC。
JVM 垃圾回收器算法
串行回收器:当 JVM 空间满了以后,stop-the-world 停止所有应用程序的线程,进行垃圾回收。(以前的都是单 CPU)
并行回收器:多 CPU 时代,当 JVM 空间满了以后,stop-the-world 多线程进行垃圾回收。(大数据用这种方式,效率比较高)
并发回收器 CMS:初始化标记静态变量等以及引用的对象 > 并发标记 > 重标记(永远表不完对象,因为对象一直在创建。所以这个阶段也会 stop-the-world) > 并发清理。(早期 Web 应用都是用这种方式,但是浪费计算资源比较多。)
G1 回收器(主流):效率更高,下面详细介绍。每次 stop-the-world 的时候,只会清理一部分区域,控制范围更小一些。
G1 垃圾回收内存管理机制
设计一个秒杀系统,主要的挑战和问题有哪些?核心的架构方案或者思路有哪些?
作业二:
根据当周学习情况,完成一篇学习总结
作业提交链接
9.1 数据库的基本原理
预编译
数据库架构
连接器
常需要几百毫秒来创建连接,程序启动时一般会预先创建连接池
语法分析器
解析 SQL 语句构建抽象语法树
语义分析与优化器
对复杂嵌套的 SQL 进行语义等价转化,利用索引进一步进行优化
执行引擎
MySQL 可以通过 explain 来查看使用的索引和处理行数
为什么预编译 PrepareStatement 更好?优势?
防止 SQL 注入攻击
提前生成执行计划,效率会更高
索引
聚簇索引
主键 ID 和记录行存储在同一个 B+树中
非聚簇索引
B+树叶子节点存储的是主键,需要回表取得其他字段
合理使用索引
添加索引操作耗时较长(分钟级别),并且会阻塞 CRUD 操作
删除不用的索引,避免不必要的增删开销
使用更小的数据类型创建索引
事务日志
在修改聚簇索引上的记录前,先写事务日志
UNDO 日志:更新前的数据
REDO 日志:更新后的数据
9.2 JVM 虚拟机架构原理
JVM 组成构架
类加载器
运行期数据区
执行引擎
字节码文件
热点代码会被 JIT 编译成机器码
其他代码会解释执行
类加载器
低层次的类加载器不能覆盖高层次类加载器已经加载的类
隔离加载类
扩展加载源
字节码加密
线程工作内存
线程操作内存变量时,需要通过线程独有的工作内存拷贝主内存变量副本来进行
多线程运行多 CPU 核心时,可能存在并发访问问题,使用 volatile 修饰
9.3 JVM 垃圾回收性能分析
回收方法
清理
压缩
复制
分代垃圾回收
新生代:Eden 区 / From 区 / To 区
老年代
JVM 垃圾回收器算法
串行回收器
并行回收器
并发回收器 CMS
G1 回收器
JVM 性能诊断工具
JPS
查看所有 Java 进程的 jvmid
JSTAT
实时监控资源和性能,包括 heap size 和垃圾回收情况
JMAP
输出所有内存对象
JSTACK
查看线程堆栈信息
JConsole
JVisualVM
9.4 Java 代码优化技巧及原理
多线程
最佳线程数
[ 任务执行时间 / (任务执行时间 - IO 等待时间) ] * CPU 内核数
线程安全代码
方法局部变量:线程安全
方法局部的对象引用:如果其他线程无法使用,线程安全
对象成员变量 :堆中对象不是线程安全的
ThreadLocal
内存泄露
长生命周期对象
静态容器
缓存
使用线程池和对象池
使用合适的 JDK 容器类
缩短对象生命周期
使用 IO buffer 及 NIO
优先使用组合代替继承
合理使用单例模式
9.5 系统性能优化案例:秒杀系统(上)
秒杀系统
9.6 系统性能优化案例:秒杀系统(下)
案例
评论