为何服务器QPS上不去?Java线程调优权威指南
在 64 位的 JVM 中,除非物理内存非常有限,并且较小的栈可以防止耗尽原生内存,否则没有理由设置这个值。另一方面,在 32 位的 JVM 上,使用较小的栈(比如 128 KB)往往是个不错的选择,因为这样可以在进程空间中释放部分内存,使得 JVM 的堆可以大一些。 耗尽原生内存 没有足够的原生内存来创建线程,也可能会抛出 OutOfMemoryError。这意味着可能出现了以下 3 种情况之一。 在 32 位的 JVM 上,进程所占空间达到了 4 GB 的最大值(或者小于 4 GB,取决于操作系统)。 系统实际已经耗尽了虚拟内存。 在 Unix 风格的系统上,用户创建的进程数已经达到配额限制。这方面单独的线程会被看作一个进程。 减少栈的大小可以克服前两个问题,但是对第三个问题没什么效果。遗憾的是,我们无法从 JVM 报错看出到底是哪种情况,只能在遇到错误时依次排查。 要改变线程的栈大小,可以使用 -Xss=N 标志(例如 -Xss=256k)。 小结 在内存比较稀缺的机器上,可以减少线程栈大小。 在 32 位的 JVM 上,可以减少线程栈大小,以便在 4 GB 进程空间限制的条件下,稍稍增加堆可以使用的内存。 监控线程与锁 在对应用中的线程和同步的效率作性能分析时,有两点需要注意:总的线程数(既不能太大,也不能太小)和线程花在等待锁或其他资源上的时间。 1. 查看线程 几乎所有的 JVM 监控工具都提供了线程数(以及这些线程在干什么)相关的信息。像 jconsole这样的交互式工具还能显示 JVM 内线程的状态。在 jconsole 的 Threads 面板上,可以实时观察程序执行期间线程数的增减。下图是一个例子。 在某个时间点,应用(NetBeans)最多使用了 45 个线程。图中刚开始有一个爆发点,最多会使用 38 个线程,后来线程数稳定在 30 到 31 之间。jconsole 可以打印每个单独线程的栈信息;如图所示,Java2D Disposer 线程正在某个引用队列的锁上等待。 JConsole 中的活跃线程视图 2. 查看阻塞线程 如果想了解应用中有什么线程在运行这类高层视图,实时线程监控会很有用,但至于那些线程在做什么,实际上没有提供任何数据。要确定线程的 CPU 周期都耗在哪儿了,则需要使用分析器(profiler)。利用分析器可以很好地观察哪些线程在执行。而且分析器一般非常成熟,可以指出那些能够通过更好的算法、更好的代码选择来加速整体执行效果的代码区域。 诊断阻塞的线程更为困难,尽管这类信息对应用的整体执行而言往往更为重要,特别是当代码运行在多 CPU 系统上,但没有利用起所有可用的 CPU 时。一般有三种执行此类诊断的方法。方法之一还是使用分析器,因为大部分分析工具都会提供线程执行的时间线信息,这就可以看到线程被阻塞的时间点。
要了解线程是何时被阻塞的,迄今为止最好的方式是使用可以窥探 JVM 内部、并且可以在较低的层次确定线程被阻塞时间的工具。Java 飞行记录器(Java Flight Recorder,JFR)就是一款这样的工具。我们可以深入到 JFR 捕获的事件中,并寻找那些引发线程阻塞的事件(比如等待获取某个 Monitor,或是等待读写 Socket,不过写的情况较为少见)。 借助 JMC 的直方图面板可以很方便地查看这些事件,如下图所示。 ![]() JFR 中被某个 Monitor 阻塞的线程 在这个示例中,与 sun.awt.AppContext.get 方法中的 HashMap 关联的锁被竞争了 163 次(超过 66 秒),使得所测量的请求响应时间平均增加了 31 毫秒。栈轨迹表明竞争源于 JSP 写java.util.Date 对象的方式。要改进这段代码的可伸缩性,可以使用线程局部的日期格式化对象,而不是简单地调用日期对象的 toString 方法。 从直方图中选择阻塞事件,然后检查调用代码,这个流程适合任何阻塞事件;这款与 JVM 紧密集成的工具使这一流程就成为可能。
如果没有商用的 JVM 可用,替代方案之一是从程序中拿到大量的线程栈并加以检查。jstack、jcmd 和其他工具可以提供虚拟机中每个线程状态相关的信息,包括线程是在运行、等待锁还是等待 I/O 等。对于确定应用中正在进行的是什么,这可能非常有用,不过输出中也有很多我们不需要的。 在查看线程栈时,有两点需要注意。第一,JVM 只能在特定的位置(safepoint,安全点)转储出一个线程的栈。第二,每次只能针对一个线程转储出栈信息,所以可能会看到彼此冲突的信息:比如两个线程持有同一个锁,或者一个线程正在等待的锁并未被其他线程持有。 JStack 分析器 (编辑:PHP编程网 - 黄冈站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |