前言
蓦然回首自己做开发已经十年了,这十年中我获得了很多,技术能力、培训、出国、大公司的经历,还有很多很好的朋友。但再仔细一想,这十年中我至少浪费了五年时间,这五年可以足够让自己成长为一个优秀的程序员,可惜我错过了,我用这五年时间和很多程序员一样在困惑和迷茫中找不到出路!
路其实一直都在那里,只是我们看不到而已!
以前我一直被公司和技术牵着走,并不是自己在选择技术,而是不自觉地被推到了这个位置上。想想有多少人对于自己将来要从事的职业和技术类型进行过深入思考和比较呢跳出编码后,我开始思考和程序及程序员职业生涯相关的问题,最后发现,影响我们走入今天的困局的竟然是一些我们常常挂在嘴边的话。
你如何定义性能p>
当被问及应用程序的性能时,大部分开发人员会假定他们需要测量某些速度值,比如每秒交易数,或者处理了多少吉字节(GB)数据……,要在尽可能短的时间里完成大量工作。
如果你是应用程序架构师,那你可能会测量更广泛的指标。与按直线逻辑执行的程序相比,你或许更关注资源利用率。你可能更重视服务间连接的性能,而不是服务本身的性能。如果你要为公司做出业务决策,应用程序的性能很多时候不是用时间而是用美元来计算的。你可能会与开发人员和架构师争论资源分配,权衡 DevOps 的成本和完成公司工作所需要的时间。
有些时候,甚至是大部分时候,“好的”编码模式盛行:小方法会恰当内联,接口和类型检查成本变低,JIT 编译器生成的原生代码紧凑又高效。但是其他时候,考虑到编译器和 CPU 的限制,我们需要手动调整代码,改变抽象和架构。有些时候,对象几乎是没什么成本的,都不用考虑我们会消耗内存带宽和垃圾收集周期。其他时候,我们要处理 TB甚至更大规模的数据集,这时候即使是最好的垃圾收集器和内存子系统,也要承受很大压力。
而现在,性能问题的答案是了解你的工具。通常这意味着你不但要了解Java 语言是如何工作的,还要知道 JVM 类库、内存、编译器、垃圾收集器和应用程序运行所在的硬件是如何交互的。在我从事 JRuby 项目的工作中,我学到一个有关 JVM 的不变的真理:所有的性能问题都没有单一的解决方案,而是有很多解决方案。技巧就是找到那些方案,并把最能满足要求的拼凑起来。
学习如何平衡应用程序的设计和可用的资源,如何监控和调优JVM,如何利用比老旧的类库和模式更高效的最新 Java 技术,如何让Java 运行如飞!
其次,看主要内容
**第1章明确优化与性能;**优化 Java 或其他语言代码的性能经常被视作一种暗黑艺术。性能分析有种神秘感,人们常常将其看作孤独的黑客在绞尽脑汁、深思熟虑之后练就的手艺。(孤独的黑客也是好莱坞最喜欢的关于计算机和操作人员的电影桥段之一。)画面是这样的:一个人能够深入了解某个系统,提出神奇的解决方案,使计算机运行得更快。
影像中经常夹杂这种不幸但常见的情况:软件团队没那么重视性能。进而出现的场景是,只有当系统已经陷入麻烦时,团队才会加以分析。所以也就需要性能“英雄”来救场了。不过现实情况有点不同。
本章首先讨论了 Java 的性能是什么,不是什么;然后介绍了经验科学和测量的基本主题,以及一个好的性能实践将用到的基本词汇和观测量;最后介绍了性能测试结果中一些常见的案例。接下来我们将开始讨论 JVM 的一些主要内容,并为理解到底是什么导致基于 JVM 的性能优化如此复杂做好准备。
**第4章性能测试模式与反模式;**性能测试会因不同的原因而进行。本章将介绍团队可能希望执行的不同类型的测试,并讨论每种类型的最佳实践。
本章的后半部分将概述一些可能会困扰性能测试或团队的常见反模式,并阐释如何重构的解决方案,以防止它们成为团队的问题。
当评估性能结果时,一定要以恰当的方式处理数据,避免陷入不科学、主观的思考中。本章介绍了一些测试类型、测试最佳实践以及性能分析中伴生的反模式。
下一章将研究底层的性能测量手段、微基准测试的陷阱,以及一些用于处理从 JVM 中测得的原始结果的统计技术。
**第5章微基准测试与统计;**本章将考虑直接测量 Java 性能数字的具体细节。JVM 的动态特性意味着性能数字往往比许多开发人员预期的要更难处理。因此,互联 上出现了许多不准确或带有误导性的性能数字。
本章的一个主要目标是确保你意识到这些可能的陷阱,并且只生成你和其他人可以信赖的性能数字。特别需要注意的是,对小块 Java 代码的测量(微基准测试)非常微妙且难以正确完成,这也是本章将要探究的主要内容,同时我们还会介绍性能工程师应该如何正确使用它。
**第7章垃圾收集高级话题;**上一章介绍了 Java 垃圾收集的基本理论。以此为起点,本章将进一步研究现代 Java 垃圾收集器的理论。这个领域有很多不可避免的权衡可以指导工程师如何选择收集器。
首先,本章将介绍并深入了解 HotSpot JVM 提供的其他收集器,其中包括停顿时间超短、通常为并发的收集器(CMS)和现代通用收集器(G1)。
此外,还将考虑一些比较少见的收集器,包括:
- Shenandoah
- C4
- 均衡(balanced)收集器
- 遗留的 HotSpot 收集器
并非所有这些收集器都在 HotSpot 虚拟机中使用,我们还将讨论另外两个虚拟机的收集器: IBM J9(IBM 的一款 JVM,之前是闭源的,目前正在逐步开源)和 Azul Zing(一款专有的 JVM),我们在 2.6 节曾介绍过。
**第8章垃圾收集日志、监控、调优及工具;**本章介绍了垃圾收集调优艺术的一些皮毛。这里演示的技术大多是针对个别收集器的,但也有一些普遍适用的基本技术。本章还介绍了一些处理垃圾收集日志的基本原则以及一些有用的工具。
下一章将讨论 JVM 的另一个主要子系统:应用程序代码的执行。我们首先将概述解释器,然后在此基础上开始讨论 JIT 编译,包括它与标准编译(或者说 AOT 编译)的关系。
**第10章理解即时编译;**本章将深入介绍 JVM 中 JIT 编译器的内部工作方式。大部分内容直接适用于 HotSpot,不过并不保证和其他 JVM 实现一致。
我们曾经提到过,与 JIT 编译相关的科学研究已经相当深入,不只是JVM,很多现代编程环境也用到了 JIT。因此,很多 JIT 技术也适用于其他 JIT 编译器。
因为这个主题非常抽象,而且技术上也很复杂,所以需要一些工具来帮我们理解 JVM 的内部工作方式,并将其以可视化方式表现出来。本章将使用的主要工具是 JITWatch,我们会先加以介绍。之后会解释具体的JIT 优化和特性,并演示如何通过 JITWatch 观察该技术及其效果。
**第11章Java语言性能技术;**本章讨论了标准 Java 集合 API 的一些性能问题,以及处理领域对象的关键关注点。
最后我们探讨了另外两个与平台级别关系密切的应用程序性能方面的考虑:终结化和方法句柄。虽然很多开发人员在日常工作中并不会遇到这两个概念,但对于关注性能的工程师来说,了解和认识它们可以充实自己的技术工具箱。
下一章将继续讨论几个重要的开源库,包括那些为标准集合类提供替代选择的库,以及日志和相关问题。
**第13章剖析;**在程序员群体中,剖析(profiling)这个术语的使用并不是非常统一。事实上,可能的剖析方法有很多种,其中最常见的有以下两种:
- 执行
- 分配
本章将涵盖这两个主题。首先重点关注执行剖析,我们会借着这个主题来介绍可用于剖析程序的工具。之后会介绍内存剖析,看一看各种工具是如何提供这种能力的。
我们将探讨对于 Java 开发人员和性能工程师而言,了解剖析器的一般操作方式是多么重要。因为剖析器有可能扭曲应用程序的行为,并表现出明显的偏差。
执行剖析是性能剖析的领域之一,在这个领域中,这些偏差就会凸显出来。谨慎的性能工程师会意识到这种可能性,并通过各种方式来弥补,包括使用多种工具进行剖析,以了解真正发生的情况。
对于性能工程师而言,同样重要的是要解决自己的认知偏差,不要致力于挖掘符合自己预期的性能行为。在第 4 章中遇到的反模式和认知陷阱就是我们训练自己避免这些问题的一个很好的开始。
**第14章高性能日志和消息系统;**日志记录是所有生产级应用程序中不可或缺的一部分,所使用的日志记录器的类型对整体的应用程序性能有非常大的影响。当涉及日志记录时,重要的是要将应用程序当作一个整体而不只是执行日志记录语句来考虑,同时注意它对其他 JVM 子系统(如线程使用和垃圾收集)的影响。
本章包含一些低延迟库的简单例子,从最底层开始,一直到一个完整的消息系统实现。显然,应该把低延迟系统的目的和目标应用于整个软件栈,从最底层的队列一直到更高层次的应用。低延迟、高吞吐量的系统需要大量的思考、经验和控制,这里讨论的许多开源项目是基于大量丰富的经验构建起来的。如果你需要创建一个新的低延迟系统,只要能从底层设计目标一直坚持到顶层应用程序,这些项目都将为你节省几天甚至几周的开发时间。
本章开始提出的一个问题是 Java 和 JVM 可以在多大程度上应用于高吞吐量的应用程序。使用任何语言编写低延迟、高吞吐量的应用程序都是非常困难的,但是在所有可用的语言中,Java 提供了最好的工具和生产效率。此外,Java 和 JVM 确实增加了另一个抽象层次,我们需要对其进行管理,并在某些情况下加以规避。同时,考虑硬件、JVM 性能和更底层的问题也非常重要。
我们在日常的 Java 开发工作中一般不会遇到这些较为底层的问题。使用本章所讨论的较新的免分配的日志库、数据结构和消息传递协议,可以大大降低进入门槛,因为很多复杂的问题已经被开源 区解决了。
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!