写点什么

week9 性能优化(三)作业和学习总结

用户头像
杨斌
关注
发布于: 2020 年 12 月 20 日

作业一:

(至少完成一个)

  • 请简述 JVM 垃圾回收原理。

JVM 垃圾回收即使将 JVM 堆中的已经不再被使用的对象清理掉,释放宝贵的内存资源。

JVM 通过一种可达性分析算法进行垃圾对象的标识。具体过程是:

  1. 从线程栈帧中的局部变量,或者方法区的静态变量出发,将这个变量引用的对象进行标记;

  2. 然后看这些被标记的对象是否引用了其它对象,继续进行标记;

  3. 所有被标记过的对象都是被使用的对象,而那些没有被标记的对象就是可回收的垃圾对象了。


进行完标记以后,JVM 就会对垃圾对象占用的内存进行回收,回收主要有三种方法:

  1. 清理:将垃圾对象占据的内存清理掉,其实 JVM 并不会真的将这些垃圾内存进行清理,而是将这些垃圾对象占用的内存空间标记为空闲,记录在一个空闲的列表里,当应用程序需要创建新的对象的时候,就从空闲列表中找一段空闲内存分配给这个对象。

  2. 压缩:从堆空间的头部开始,将存活的对象拷贝到一段连续的内存空间中,那么其余的空间就是连续的空闲空间。

  3. 复制:将堆空间分成两部分,只在其中一部分创建对象,当这个部分空间用完的时候,将标记过的可用对象复制到另一个空间中。



清理:把已经没用的空间标记为可用空间。

压缩:清理有个短板,空间不是连续的,压缩就是把还在用的 copy 放在前面。

复制:压缩还是需要成本的,速度较慢;分两块区域会更好一点。

JVM 分代垃圾回收



  1. 创建新对象在 Eden 区,当 Eden 区满了以后,就会进行 Young GC,把在用的对象 copy 到 From 区;

  2. 当 Eden 区再次满了以后,再次进行 YoungGC,把 Eden 区和 From 区的在用对象,copy 到 To 区;

  3. 当多次 Eden 发送 YoungGC,把一些还用的对象放到老年代;

  4. 当老年代满了以后,就会进行 Full GC。这是要应用线程都要暂停,进行 Full GC。


JVM 垃圾回收器算法



  1. 串行回收器:当 JVM 空间满了以后,stop-the-world 停止所有应用程序的线程,进行垃圾回收。(以前的都是单 CPU)

  2. 并行回收器:多 CPU 时代,当 JVM 空间满了以后,stop-the-world 多线程进行垃圾回收。(大数据用这种方式,效率比较高)

  3. 并发回收器 CMS:初始化标记静态变量等以及引用的对象 > 并发标记 > 重标记(永远表不完对象,因为对象一直在创建。所以这个阶段也会 stop-the-world) > 并发清理。(早期 Web 应用都是用这种方式,但是浪费计算资源比较多。)

  4. G1 回收器(主流):效率更高,下面详细介绍。每次 stop-the-world 的时候,只会清理一部分区域,控制范围更小一些。


G1 垃圾回收内存管理机制



  • 设计一个秒杀系统,主要的挑战和问题有哪些?核心的架构方案或者思路有哪些?

作业二:

  • 根据当周学习情况,完成一篇学习总结

作业提交链接

https://jinshuju.net/f/c9pC4Q

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 系统性能优化案例:秒杀系统(下)

案例


用户头像

杨斌

关注

还未添加个人签名 2020.03.17 加入

还未添加个人简介

评论

发布
暂无评论
week9 性能优化(三)作业和学习总结