2

大量的个人经验、轶事证据和一些初步分析表明,Java 服务器(通常运行 Oracle 的 1.6 JVM)在负载相当大的情况下具有更快的响应时间(显然仅在一定程度上)。

我不认为这纯粹是热点,因为当流量减少时响应时间会再次变慢。

在许多情况下,我们可以通过平均来自服务器日志的响应时间来证明这一点……在某些情况下,它的平均速度高达 20%,并且标准偏差更小。

谁能解释为什么会这样?这可能是真正的影响,还是平均值只是误导?多年来,我已经通过几份工作看到了这一点,并且倾向于将其陈述为事实,但没有解释原因。

谢谢,埃里克

4

1 回答 1

1

编辑一个相当大的措辞编辑,并在整个过程中添加更多细节。

一些想法:

  1. 当一段代码的执行次数明显多于其他部分(这是程序的热点)时,热点就会启动。从那时起,这使得那段代码(对于正常路径)明显更快。热点编译后的调用率并不重要,所以我认为这不会导致您提到的效果。

  2. 效果是真的吗?用统计数据欺骗自己很容易。不是说你是,但要确保你所有的运行都包含在结果中,并且所有其他效果(如其他程序、活动和你的监控程序在所有情况下都是相同的。我有不止一个有我的监控程序,例如 top,会导致行为不同)。有一次,当数据库上的缓存预热时,应用程序的性能显着提高- 同一数据库实例上的其他应用程序存在内存压力。

  3. 很可能涉及操作系统和/或 CPU。当主程序从主要运行变为主要等待 I/O 时,操作系统和 CPU 都会主动和被动地做一些事情来提高主程序的响应能力,反之亦然,包括:

    1. 操作系统在不使用时将内存分页到磁盘,并在程序运行时将内存分页到 RAM
    2. 操作系统将缓存经常使用的磁盘块,这又可以提高应用程序的性能
    3. CPU 指令和内存缓存填充活动程序的指令和数据

Java 应用程序对内存分页效果特别敏感,因为:

  1. 典型的 Java 应用程序服务器会将几乎所有空闲内存预分配给 Java。大内存使应用程序天生对内存效应更敏感
  2. 用于管理 Java 内存的分代垃圾收集器最终会在大量页面上创建新对象,因此对应用程序的每个请求都需要比其他语言更多的页面请求。(这主要适用于没有经过多次垃圾回收的“新”对象。提升到永久代的对象实际上存储得非常紧凑)
  3. 由于系统上分配了大部分可用的物理内存,因此内存总是存在压力,并且最大、最近运行最少的应用程序是页面输出的完美候选者。

考虑到这些因素,与内存需求较小的环境相比,页面丢失的可能性更大,因此性能受到影响。这些在 Java 闲置一段时间后尤其明显。

如果您使用 Solaris 或 Mac,出色的dTrace可以跟踪特定于应用程序的内存和磁盘分页。JVM 有许多 dTrace 挂钩,可用作启动和停止页面监控的触发器。

在 Solaris 上,您可以使用大内存页面(甚至超过 1GB 大小)并将它们固定到 RAM,这样它们就永远不会被分页。这应该可以消除上述内存页面问题。请记住为磁盘缓存和其他系统/维护/备份/管理应用程序留出大量可用内存。我确信其他操作系统也支持类似的功能。

TL/DR:现代操作系统中当前正在运行的程序在几秒钟后会显得运行得更快,因为操作系统会将程序和数据页面从磁盘带回,将经常使用的磁盘页面放在磁盘缓存中,并且操作系统指令和数据缓存将对主程序来说往往是“温暖的”。这种效果并不是 JVM 独有的,但由于典型 Java 应用程序的内存需求和垃圾收集内存模型,这种效果更加明显。

于 2012-12-03T09:50:15.103 回答