Mark Lam has been a virtual machine engineer in the JavaME CDC team at Sun Microsystems for over 6 years. Before joining Sun, he was a real-time embedded systems developer for 6+ years, working on application frameworks, graphics systems, networking protocols, game development, and fault tolerant systems amongst other things, on devices ranging from 64KB 8bit uControllers to 32-bit RISC machines.
原文URL:http://weblogs.java.net/blog/mlam/archive/2006/11/performance_how.html#more

性能:太多的好事?
               这篇文章需要开发者有PhoneMe Advanced VM和J2ME方面比较深奥的知识。
              如果你已经看过了phoneMe Advanced VM的代码,你可能已经注意到许多函数和结构都是以cvm为前缀的。CVM是sun公司CDC VM的名称,而cvm作为前缀是VM代码(特别是全局函数和结构)的标准习惯。这是所有使用sun公司CDC技术工作过的人的普遍常识,但在这里我还是要强调一下。另外,我简单的以CVM来代替phoneMe Advanced VM。
现在让我们开始今天的主题。。。
性能
           通常,没有用户会抱怨,当他们的软件有很好的性能。无论如何,性能伴随着价格。通常,这意味着复杂的代码和更好的硬件。这还意味着需要更多的内存来运行软件。对JavaME VM来说,它的目标是资源受限的嵌入式设备。这是一个明确的关系。因此,一些性能上的工作需要合理的代价。这意味这平台开发者不能做所有他们知道的书本上的优化方法。
          这样说,我希望你知道我没有说这些是因为CVM的性能是窘迫的。直到我们吃的,CVM是这个领域最快的虚拟机,如果不是最快的,给你一个关于CVM性能的想法。几年前,我们把CVM同JavaSE1.3的基于SPEC JVM98子集的client VM进行了比较。我们使用子集是因为SPEC JVM98使用了已经从CDC移出的不受赞成的API。因此,我们做了一些内部“移植”对这个比较。这个比较在PowerPC,PowerMac和Solaris SPARC机器上进行。同JavaSE比,CVM显示了80%~90%的性能,只有10%的静态footprint。你应该知道这是老的数据。JavaSE已经有了很大的提高,CVM也是。注意:我仅仅是共享这些比较而给你一个JavaME能达到的性能等级的概念,我没有说任何关于哪一个VM更好。
         因此,当我们谈论性能的时候,人们首先谈论的VM的一个组成是动态适应编译。而作为JIT,下面我会围绕比较谈关于一些性能的事。我会接触其他非JIT相关但又重要的领域或主题
静态编译 VS 运行时编译
           一个最大的错误是,工程师会在JIT开始执行从其他编译课本来的优化而不做太多考虑。这些优化技术中的一些是意味深长的,而一些不是。有一点,课本经常教的是静态编译。JIT,在其他方面,是动态编译。这是JavaME的资源受限请求的要素。你可以在它们的属性中找到对比。下面是2中技术的比较:
Static compiler                                                                       JavaME JIT compiler
能提供少量内存给编译工作                                                   必须最小化或限制使用的工作内存
能够提供更多的时间和CPU周期给编译工作                      必须最小化或限制CPU的消耗
假设所有的方法在编译时都是可用的                                   只能工作与一个子集
编译所有的方法                                                                       只编译正在使用的方法。
必须编译所有类型的代码                                                   只需用编译通用的类型,让解释器处理那些不常见的实例
             注意,很多静态编译都假定更多内存和CPU资源的可用性。因此,他们的编译技术有很多相似的假定。明显的,这些技术的一部分不适用于JavaME。
                注意,尽管java平台是一个动态环境,可以期望部分代码在运行时下载。后期绑定是Java VM和语言的特点。 这不匹配静态编译的假定:整个应用程序代码必须在编译期可用。
JIT的能力让解释器处理不常用的案例的执行,同样也减少非紧急代码在资源上的消耗(在编译代码和编译footprint)
             批评家会说在我上面基于广泛性的表格里的需求,在今天的编译技术水平下不是真的。为什么,对的,我同意。我假设静态编译也来源静态链接。但记住,你的编译课本可以没有包括这2个中的任一个。我也使用静态编译的严格定义。例如:我认为它是编译静态代码。
真实世界的执行会加入一些能力,包括动态代码(可以下载),但这些不是严格的静态编译。这里的要点是你不必盲目的应用一流的编译技术。这些技术常常对不同的系统(这对类似于java的平台)做目标和最优化,因此他们可能不适合这里。
            人们可能有这样的误解,通过静态编译的代码要运行的比实时编译的要快。这不是全对的,实时编译的代码能够超越静态编译的代码。一个关键的原因是,java平台是动态并且后期绑定的。我会在以后详细的讨论这个。
           因此,有很多的原因导致静态编译不适用,甚至当你关心的资源和性能受限大打折扣。
JavaSE Hotspot VS CVM
        因此我们不能从编译器课本挖掘出诀窍。那从JavaSE VM可以得到诀窍吗?回答是“可能”。首先,这是资源受限的问题。JavaSE已经和有许多资源的大系统匹配了。这完全是合理的和可接受的,他们使用这些资源给你最好的性能在你的话费下。但当这些资源在你的设备上不可用时,这些技术可能就不能用了。
            另一点对普通开发者来说不是那些显而易见,JavaME 执行(像CVM)不仅仅是JavaSE的小版本。JavaSE目标设备的类型和JavaME有很大差别。CVM不是因为比JavaSE Hotspot少了一些功能而变小,CVM体系被设计的它可以工作在不同的嵌入式设备上。在它设计上的每一级,不同的选择会导致速度-空间的权衡。由于这个原因,用在JavaSE里的技术可能不能应用在CVM里,因为它们有不同的权衡。
                 给你一些例子来说明JavaME设备和JavaSE的不同,一段时候前,我的一个JavaSE方面的同事发现了当他应用一个可靠的技术来改善高速缓存位置,基于一个基准他能得到20%性能的提升。这抓住了我的注意。20%是不容忽视的,因此,我应用这个技术到CVM。令我吃惊的是,基于同样的基准,性能下降了70%,发生了什么?不同的是,JavaSE运行在一个有大量高速缓存(上百KB甚至是几兆)的服务器上。而我运行在只有32KB高速缓存的基于ARM处理器的设备上。这个改良的高速缓存位置在这儿制造了一个冲突。
 这个有效提升JavaSE的技术相对CVM来说,这也不是一个精确的例子。在这个例子里,他可以解决。但如果最优化代码,这项JavaSE技术可用于那些有着巨大缓存的设备?把这个技术应用在CVM实际上会造成那些没有大量高速缓存的JavaME设备性能的大幅下降。
              因此,关键是我们不要盲目的应用从JavaSE来的任何重要技术。注意上面的例子也说明了JavaSE VM运行的不比CVM快,当它运行在JavaME设备上时,即便你有大量的RAM(不是系统高速缓存)。这就像你想要你的汽车使用火箭引擎而有更大的马力。这听起来是一个不错的主意,但你的燃料系统不能支持它。结果也不比一般的汽车快。什么也没有改变。
              JavaME不仅仅是JavaSE的缩小版。对比JavaSE和JavaME就像对比苹果和橙子。
 基准
                 最后,确定优化是否工作的最好方法就是实验。 我们经常自己做这些事情。当一个念头失败,我们不混合基本代码。检测优化是否联合的一个重要的标准是,花费了多少成本在小组的资源分配上。另外,它带给了你多少性能的提升。
                 测量性能的提升,你需要运行某个类别的基准。一个常见的错误是人们运行了一个小的基准仅仅在测试一个优化提升的范围。真实世界的应用程序可能不只参加了一个循环和一个代码范围。因此,基于真实世界应用程序的基准是一个可靠的指示。对JavaMe来说,我们喜欢SPEC JVM98,但像前面说的,它不能不修改那些不赞成的方法而运行在CDC上。另外我们还喜欢EEMBC的GrinderBench。
               如果可能,运行你的基准在JavaME类型的设备上。就像上面指出的,JavaME不同于JavaSE,你改变在JavaSE类型的桌面或服务机器的的基准将给你指示,改变的结果是否有增长。但不同的JavaME设备,你得到的结果不完全一样,需要有适当的工程判断。
另外的性能
                一般的,java平台的性能不仅仅指执行引擎(解释器,JIT)。VM运行时和类库的品质也是游戏的一大部分。有些时候,它们甚至比VM重要。这包括主要依靠本地代码(相对于java代码)的graphics/GUI应用程序。无论如何,这不是意味着他们不依靠VM来运行。严格来说,VM运行时库是VM实现的一部分,我们也需要优化它。
                VM也能提供帮助机制使类库能执行的更好。他们需要共同工作。
               最后,有一件关于本地代码的事情。一些人认为他们的代码会执行的更快如果他们主要代码都是本地代码。这确实是个谬论,因为一系列的原因,使用本地代码确实会造成性能的下降比起一些功能使用java字节码。
               所有的这些都会在后面讨论。
这对你意味着什么
           性能是个复杂的主题。我们在这里仅仅是触及到了它的表面。正如我上面想要指出的,事情不是总想它们看起来的样子。当试着对JavaME系统执行性能提高的工作,对于嵌入式系统开发者来说,谨慎的思考是必要的。每一种优化技术需要在这个地方个别的进行评估。
            祝有美好的一天!:)


评论

该日志第一篇评论

发表评论

评论也有版权!