1 / 64

Writing Efficient Java Series (B2) 深入 JVM 虚拟机 ( 下 )

Writing Efficient Java Series (B2) 深入 JVM 虚拟机 ( 下 ). 2013 . 9 共享软件开发及管理部 季怡. 内容. 基础课程 A1 J2SE 基础 从 String 开始 集合与数组 A2 日志与 JDBC 正确使用日志 JDBC 的操作优化 A3 程序性能分析与优化 分析与评估程序性能 常用优化手段 A4 编程定式. 进阶课程 B1 深入 JVM ( 上 ) 理解 JVM 执行引擎 Java 的编译期处理 B2 深入 JVM ( 下 ) 编译期优化的利用 动态硬编码技术

avari
Download Presentation

Writing Efficient Java Series (B2) 深入 JVM 虚拟机 ( 下 )

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Writing Efficient Java Series (B2) 深入JVM虚拟机(下) 2013.9 共享软件开发及管理部季怡

  2. 内容 基础课程 • A1 J2SE基础 • 从String开始 • 集合与数组 • A2 日志与JDBC • 正确使用日志 • JDBC的操作优化 • A3 程序性能分析与优化 • 分析与评估程序性能 • 常用优化手段 • A4 编程定式 进阶课程 • B1 深入JVM (上) • 理解JVM执行引擎 • Java的编译期处理 • B2 深入JVM (下) • 编译期优化的利用 • 动态硬编码技术 • JVM运行期优化 • B3 高性能并发 • B4 故障分析与诊断

  3. usega of byte-code/compiler optimization 字节码技术和编译优化的利用

  4. 开发者能做的 • 理解机制 减少不必要的性能开销 • 从一个开源项目说起: • fastjson ——https://github.com/alibaba/fastjson • 阿里巴巴 温绍锦 • 比所有json工具快,比google的protocol buf等二进制快

  5. 近况 • 随着稳定性和适应范围的扩大,性能略有下降。 • 部分极端场合还有性能BUG

  6. Fast-json的核心技术 • 高效文本解析器 • 基于动态字节码技术实现硬编码

  7. 通用编码与硬编码

  8. 硬编码的性能提升 • 使用“硬编码”后—— • 不再有反射开销 • 循环已被展开,不再有开销 • 部分变量转为常量 • 没有随机访问 • 动态“硬编码”技术 (字节码技术) • 第一次执行时 • 为每个User Bean生成专用的序列化、反序列化类

  9. 细节处理 • 方法内联 • fast-json中的很多方法都是非常长的,相当于人工执行了一些方法内联 • 自行编写的并发实现 • final关键字的使用 • 减少对象创建 • ……

  10. FastJson为什么快 今天已经打下了基础 回去可以和小伙伴一起阅读fast-json源码了!

  11. JVM如何找寻方法 • 静态分派 • 编译期间计算方法重载的版本 • 找寻”最合适的”方法 • 动态分派 • 根据编译产生的“方法签名” • 找寻方法的接收者

  12. 变量和方法尽可能private 性能逐渐下降

  13. 分支处理 • if … else if … else …模型中 • 将出现概率高的分支放在前面 • 在可读性条件允许的范围内 • 原因:if else模型是顺序执行的 • switch不是,因此不适用此规则

  14. 能不用的分支就不要用 有些人喜欢用分支为boolean变量赋值

  15. 分支控制 switch的编译实现 • switch有两种实现 • 逐条判断? 我的switch不可能那么笨 • 选择哪种实现由编译器基于优化规则处理

  16. tableswitch 的可能实现 9: invokevirtual #38; //Method java/lang/Thread$State.ordinal:()I 12: iaload 13: tableswitch{ //1 to 6 1: 52; 2: 74; 3: 74; 4: 74; 5: 74; 6: 63; default: 82 } 52: getstatic #44; //Field java/lang/System.out:Ljava/io/PrintStream; 55: ldc #50; //String 线程还没运行。 先获取分支范围 按跳转值作为偏移量 直接到表中获取下一条指令的地址 switch为什么只能用int型做跳转参数, 这样就可以理解了。

  17. lookupswitch的可能实现 11: invokevirtual #91; //Method java/lang/String.hashCode:()I 11: lookupswitch{ //3 70499: 44; 74231: 56; 77118: 68; default: 86 } 44: aload_2 45: ldc #96; //String Feb 47: invokevirtual #98; //Method java/lang/String.equals:(Ljava/lang/Object;)Z 将分支条件放入下列适合随机访问的数据库结构中,运行时得到下一指令的入口 跳表结构查询复杂度:O(log n) 哈希表结构 查询复杂度: O(1) ——无碰撞下

  18. switch小结

  19. Way to Ultimate performance 字节码技术

  20. 字节码技术 • 实现“硬编码”(高性能计算) • 在运行期间,动态生成代码的技术 • 针对运行期业务场景,固化业务逻辑。 • java计算性能的终极解决办法 • 查找和分析类 • ClassScanner • 动态代理 / AOP • Entity Enhancer

  21. java字节码框架

  22. CGLib bean copier • net.sf.cglib.beans.BeanCopier • org.springframework.cglib.beans.BeanCopier 秒杀: org.apache.commons.beanutils.BeanUtils.copyProperties(Object, Object) org.apache.commons.beanutils.PropertyUtils.copyProperties(Object, Object) org.springframework.beans.BeanUtils.copyProperties(Object, Object) org.springframework.beans.BeanWrapper + 循环赋值

  23. Javasist示例 在类的每个set方法最前面植入代码,去调用prepareSet()方法

  24. Why ASM • 最基础 • 别的框架能做的,ASM一定能做。ASM能做的,别的框架不一定能做。 • 更轻,更小,更快 • byte code其实很简单 • 中文资料和教程越来越多 ASM核心类只有15~20个,代码400K。不依赖任何第三方库

  25. 大量的框架都内嵌了ASM并使用 • 为了让自己的框架看上去更独立?! • 避免和其他框架冲突 • 避免版本兼容问题

  26. 类的结构

  27. 简单示例

  28. Descriptor

  29. ASM中方法和字段的修饰 • 描述一个方法或字段

  30. ASM ClassReader • 可以读取(解析class文件) • 被ClassVisitor所访问

  31. 示例一 • EntityScanner

  32. ClassReader的访问者模式

  33. ClassReader示例2

  34. ASM ClassWriter • ClassWriter也是一个访问者 • visitMethod (MethodVisitor) 可以生成代码 • visitField (FieldVisitor) • visitSource • visitInnerClass • 如果用new ClassReader(out.data).accept(new ClassWriter());就相当于在ClassWriter中复制了原始类的全部结构

  35. ASM的装箱和拆箱实现 var.TypeValue() “()I” “intValue” Type.valueOf() “(I)Ljava/lang/Integer;” “java/lang/Integer”

  36. ASM实现if else

  37. 使用ASM制作动态代理

  38. Runtime Opmization JVM运行期优化

  39. 运行期优化的手段_JIT

  40. HotSopt中 • 一个 byte code Interpreter • 解释执行字节码 • 两个JIT Compiler • C1 (client)编译器 • 轻量级、编译时间短、占用内存少 • 使用前端程序 • C2 (server)编译器 • 重量级、执行效率高、大量编译优化 • 适用服务器

  41. 解释器与编译器 即时编译 C1 编译器 解释器 Client Compiler Interperter C2 Server Compiler 逆优化

  42. JIT的历史 Dalvik VM Google

  43. JVM的发展和融合

  44. HotSpot的工作模式 • -server • -client • -Xint • -Xcomp • -d64 • HP unix等一些环境下的JVM,用-d64或-d32来指定使用32位JVM还是64位JVM

  45. Server VM和Client VM • 就只有编译器(策略)的区别

  46. 查看编译器工作状态

  47. 查看编译器工作状态 • -XX:+PrintCompilation • -XX:+PrintInlining • -XX:+PrintAssembly 38 1 java.lang.String::hashCode (64 bytes) 39 2 java.lang.String::indexOf (151 bytes) 39 3 sun.nio.cs.ext.DoubleByteDecoder::decodeSingle (10 bytes) 39 4 java.lang.String::charAt (33 bytes) 39 5 java.lang.String::lastIndexOf (156 bytes) 40 6 java.io.Win32FileSystem::normalize (143 bytes) 40 7 java.lang.String::indexOf (166 bytes) 41 8 java.lang.AbstractStringBuilder::append (40 bytes) 42 9 java.io.Win32FileSystem::isSlash (18 bytes) 42 10 s java.lang.StringBuffer::append (8 bytes) 42 11 java.lang.Object::<init> (1 bytes) 43 12 sun.misc.ASCIICaseInsensitiveComparator::compare (143 bytes) 43 13 java.io.Win32FileSystem::normalize (231 bytes) 44 14 java.lang.StringBuilder::append (8 bytes) 44 15 ! sun.net.www.ParseUtil::decode (194 bytes) 45 16 java.lang.CharacterDataLatin1::getProperties (11 bytes) 45 17 java.lang.String::toLowerCase (436 bytes) 46 18 java.lang.Character::toLowerCase (162 bytes) 46 19 java.lang.CharacterDataLatin1::toLowerCase (36 bytes) 46 20 java.lang.String::replace (142 bytes)

More Related