在多核服务器上提升 Java 应用性能

摘要

企业 Java 应用无需修改源代码,既可以充分利用多核处理器的优势。本文中,通过将一个 J2EE 应用从单核迁移到双核英特尔处理器环境,我们实现了约 1.90 倍的性能提升。我们将讨论 J2EE 应用的性能特征,以及为什么这些应用已经非常适合双核处理器。同时还将讨论一些双核处理器的新特性,这些特性将有助于支持现有应用发挥出更高性能。

简介

与 C 语言等传统编程语言不同,Java 提供了内嵌的并发机制,包括对线程和锁定的支持 [《Java 编程语言规范》,作者 Gosling、Joy、Steele、Bracha,2000 年]。在 Java 中创建一个应用线程就像定义一个扩展 java.lang.Thread 的类并为该类创建一个实例一样简单。[1]挂起、恢复和调度等线程操作也像调用线程对象中的一种方法一样简单。此外,多数基于 Java 的应用框架都提供了一种环境来进行轻松的线程管理。对于 BEA WebLogic 服务器和 IBM WebSphere 应用服务器等大多数 J2EE 应用,这一点尤为明显。这些应用具有复杂的内置线程管理系统,可以充分利用 Java 编程语言的并发特性。应用开发人员只需依靠 J2EE 应用服务器的线程管理功能即可,不用担心直接进行线程管理的问题。例如:J2EE 应用服务器将用一个内部线程池来处理同一 Enterprise Java Beans (EJBs) 容器中的不同 EJB,以此进行线程管理。线程及其智能管理的使用,对于必须迅速处理大量来自多个客户端的同步请求的 J2EE 应用非常重要。

 

Java 语言特性和 J2EE 应用服务器的复杂线程处理功能简化了 J2EE 应用中的并发管理并提高了其效率,然而这些应用最终必须在处理器上执行。

英特尔全新双核处理器在一颗芯片中封装了两个功能全面的处理核心。与单核处理器相比,双核处理器通过大幅度提升前端总线速度提供了双倍的解码与执行资源、双倍的 TLB 和指令与数据一级缓存,以及双倍的二级缓存资源。由于为应用提供了更多可用的处理器资源,所有这些特性都极大地提升了多线程应用的性能。

 

要充分发挥英特尔双核处理器的作用,单线程应用必须重新进行编写和编译,而由于 J2EE 应用服务器已经高度线程化,所以几乎不需要成本、或只需很少的成本,即可通过将其迁移到双核处理器来提高性能。这意味着现有 J2EE 应用应该能够通过从单核处理器迁移到双核处理器来充分发挥性能优势,且无需对源代码进行任何修改。


在接下来的部分,我们将探讨多层 J2EE 应用在单核处理器和双核处理器系统中运行时的性能。

 

J2EE 应用性能比较

我们对一个运用了多种 J2EE 技术的多层 J2EE 应用在单核和双核处理器上运行的性能进行了调查和比较,这些技术包括:web 容器、Enterprise Java Bean (EJB) 容器、Java 消息服务 (JMS)、事务管理和数据库连接。该应用使用了一系列的 J2EE 服务,包括分布式事务、对象持久性、动态网页生成、消息传送与异步任务管理和事务型组件等。

 

我们用来运行这个 J2EE 应用的应用服务器创建了若干线程来处理不同类型的客户端请求,例如基于配置文件的远程方法调用 (RMI)。由于双核处理器能更高效地处理更多线程,我们为单核和双核处理器系统指定了不同的线程使用数量,以便让两个系统都发挥最大性能。不过,部分 Java 应用服务器已经具备了根据服务器负载和响应时间自动调整线程数量的功能,因此这一步不是必需的,可以根据所使用的 Java 应用服务器来决定。

 

不仅如此,由于双核系统的数据吞吐量更高,在其上运行应用有可能造成单核系统中见不到的性能瓶颈,因此我们对双核系统执行了性能分析,以消除任何可能存在的性能瓶颈(例如网络)。

 

这个 J2EE 应用是一个三层应用,由客户端层(驱动器)、应用服务器层和数据库层组成。图 1 展示了这一 J2EE 应用如何配置和部署的一种可能情况

 

图 1 一个多层 J2EE 应用

 

本图中采用了一个多层应用服务器集群来处理来自客户端(驱动器)的请求。这是一种可扩展的架构,其总体性能取决于应用服务器的数量和每台应用服务器的性能。在下面的表格中,我们对比了单个应用服务器节点上的性能。对比采用了两台英特尔服务器:其中一台服务器采用了两个单核处理器,另一台采用了两个双核处理器。表 1 展示了这次对比中所用的详细系统配置。

 

表 1. 详细系统配置

 

单核

双核

处理器

双路 Intel® Xeon™ 处理器,运行频率 3.6GHz,每个处理器封装中包含 2M 二级缓存

双路 Intel® Core™ 2 双核处理器,运行频率 3.0GHz =

内存

8GB DDR2

8GB FB-DIMM

操作系统 (OS)

RedHat* Enterprise Linux AS 4.0 更新 2

数据库处理器

四路 Intel® Itanium® 2 处理器,1.6GHz,9M 三级缓存

 

如表 1 所示,单核和双核配置都采用了同样的数据库后端。此外,单核应用服务器和双核应用服务器都在相同的软件堆栈上运行,包括操作系统、Java 虚拟机、J2EE 应用服务器及相同的应用。对比中唯一不同的组件,是应用服务器节点上使用的硬件,包括处理器和内存类型[2]

 

图 2 单核和双核应用服务器的性能对比

 

图 2 展示了我们的 J2EE 应用分别在单核处理器和双核处理器系统中运行时的性能。性能是以数据吞吐量来衡量的,其衡量依据是应用服务器在特定响应时间标准范围内成功完成的事务数量。如图 2 所示,我们的 J2EE 应用在相同的软件堆栈上运行的性能,在双核处理器服务器上比在单核处理器服务器上提升了约 1.90 倍。值得注意的是,我们的 J2EE 应用出现锁争用的情况相对较少,并且遭遇其它性能瓶颈的 J2EE 应用可能需要进一步调试。我们将在接下来的部分解答性能分析的问题。

 

性能分析方法

由于前面所述的运行时特征不同,并不是所有的应用都能从迁移到双核处理器获得同等的好处。不仅如此,应用在迁移到双核处理器上后,还有可能产生新的性能瓶颈。J2EE 应用尤其如此,因为它们常常涉及多台通过一个网络互联的计算机,例如一台数据库机器。要解决可能产生的性能瓶颈,不但要对不同的系统单独进行检测,以解决系统内部的性能问题(例如磁盘瓶颈),还要与其它系统联合进行检测,以解决系统之间的性能问题(例如网络瓶颈)。

我们推荐的性能分析方法是从上到下、由数据驱动的迭代方法,这一方法在 Chow et al 的《企业 Java 性能:最佳实践》中有详细解释。[《英特尔技术杂志》,第 1 期,第 7 卷,2003 年 2 月]。作者在其中建议采用系统的性能数据检测方法,从较高级别的系统数据到较低级别的微架构数据进行检测,以发现性能问题。图 3 解释了这种自上而下的方法。

 

图 3 - 从上到下的性能分析方法

 

一旦通过这种从上到下的方法发现了性能问题,就需要采用“数据驱动”的“迭代”方法来解决这些问题。“数据驱动”是说必须测量性能数据来为后续步骤作指导,而“迭代”则表示这个过程必须不断重复,直到达到希望的性能水平。图 4 展示了这一迭代方法。

 

图 4 – 迭代性能分析方法

 

通过这种从上到下、数据驱动的迭代性能分析方法,我们可以充分享受迁移到双核处理器系统所带来的优势。

进行迁移

我们已经在前面介绍过,提升某些线程化 J2EE 应用性能的最简便的方法就是迁移到双核处理器。英特尔全新双核处理器提供了双倍的解码与执行资源、TLB 和指令与数据缓存,并借此实现了性能提升。此外,由于许多J2EE 应用本身就是多线程化的,而且大多数 J2EE 应用服务器已经内置了复杂的线程功能,所以 J2EE 应用开发人员无需对源代码进行任何修改,即可充分利用英特尔的双核处理器。从上到下、数据驱动的迭代性能分析方法将确保 J2EE 应用能够充分利用双核处理器系统的优势。


[1]当然了,这是一种对 Java 线程的相当简单的看法。还有其它可以在 Java 中创建应用线程的方式,以及许多可以在其中执行的操作。

[2]这两台服务器上的内存容量是始终保持一致的。

Para obtener información más completa sobre las optimizaciones del compilador, consulte nuestro Aviso de optimización.