专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »Java教程 » 关注性能:改进您的开发过程 »正文

关注性能:改进您的开发过程

来源: 发布时间:星期日, 2009年3月29日 浏览:0次 评论:0
?犘阅苁? Java 平台屡屡受到指责个方面然而Java 平台巨大成功也使得对性能问题作番严肃调查研究颇有必要在这个新专栏中无畏优化大师 Jack Shirazi 和 Kirk Pepperdine分别是 JavaPerformanceTuning.com 董事和 CTO他们在整个 Internet 上推行性能大讨论展开他们所碰到问题并加以澄清本月他们来到 JavaRanch讨论有关编译速度、异常以及堆长度调优等方面话题?牐犐细鲈拢?我们在 JavaRanch Big Moose Saloon 板块上花了大量时间以便查看 JavaRanch 生手会提出什么样性能方面疑问后来发现大部分问题都是有关 J2SE 和开发过程——提出问题主要是有关 Java 语言、核心类以及如何改进他们开发过程编译速度 ?牐犇?是否曾发现您编译阶段很慢?是不是 javac 所花时间太长?那么试试 Jikes 编译器吧在创建 . 文件时它会加入额外“动力”这就是新兴 Jikes它拥有完整 Java 源支持(可能会引起 VeryError不支持所有 javac 选项字节码可能不像所说那么好而且性能也可能受到影响因此在使用的前请务必阅读使用手册) ?牐犓?以说在 JavaRanch 上对 Jikes 讨论不像我们自制广告那么直接但是有读者也明确指出Jikes Java 编译器是设计用来加快编译速度知道这点很有用尤其是对于那些需要编译很多文件项目更是如此不过要清楚虽然 Jikes 有助于加快开发进程但是对于最后编译最好还是使用和在生产中将要使用 JVM 起提供那个编译器区别 JVM 版本会有区别情况所以当使用来自区别 JVM 编译器时就可能引发问题异常开销很大 ?牐犑堑模?异常开销很大那么这是不是就意味着您不该使用异常?当然不是但是何时应该使用异常何时又不应该使用异常呢?不幸答案不是下子就说得清 ?牐犖颐且?说您不必放弃已经学到 try-catch 编程习惯但是使用异常时可能会遇到麻烦创建异常就是个例子当创建个异常时需要收集个栈跟踪(stack track)这个栈跟踪用于描述异常是在何处创建还记得当代码中抛出个意料的外异常时您所看到输出来栈跟踪吗?像下面这个: ?牐燛xception in thread "" my.corp.DidntExpectThisException at T.noExceptionsHere(T.java:13) at T.(T.java:7) ?牐牴菇ㄕ庑┱桓?踪时需要为运行时栈做份快照正是这部分开销很大运行时栈不是为有效异常创建而设计而是设计用来让运行时尽可能快地运行入栈出栈入栈出栈让这样工作顺利完成而没有任何不必要延迟但是当需要创建个 Exception 时JVM 不得不说:“先别动我想就您现在样子存份快照所以暂时停止入栈和出栈操作笑着等我拍完快照吧”栈跟踪不只包含运行时栈中两个元素而是包含这个栈中个元素从栈顶到栈底还有行号和切应有东西如果在个深度为20栈中创建了异常那么就别指望只记录顶部几个栈元素了——您得完完整整地记录下所有20个元素 或 Thread.run (在栈底)到栈顶记录整个栈 ?牐犚虼耍?创建异常这部分开销很大从技术上讲栈跟踪快照是在本地思路方法 Throwable.fillInStackTrace 中发生这个思路方法又是从 Throwable contructor 那里但是这并没有什么影响——如果您创建个 Exception就得付出代价好在捕获异常开销不大因此可以使用 try-catch 将核心内容包起来您也可以在思路方法定义中定义 throws 子句这样对性能不会造成什么损失例如: ?牐爌ublic Blah myMethod(Foo x) throws SomeBarException { ?牐?.... ?牐牬蛹际跎辖玻?您甚至可以随意地抛出异常而不用花费很大代价招致性能损失并不是 throw 操作——尽管在没有预先创建异常情况下就抛出异常是有点不寻常真正要花代价是创建异常 ?牐爐ry { ?牐? doThings; ?牐? (true) ?牐? throw SomeException; // cos my program runs too fast ?牐爙 ?牐燾atch(SomeException e) { ?牐? doMoreThings; ?牐爙 ?牐犘以说氖牵?好编程习惯已教会我们不应该不管 3 7 2十就抛出异常异常是为异常情况而设计使用时也应该牢记这原则但是您不想遵从好编程习惯Java 语言就会让您知道那样做可以让您运行得更快从而鼓励您去那样做最大堆长度 ?牐犜谖颐欠梦使?所有讨论组中有关 JVM 堆问题不断冒出在 JavaRanch 上有次讨论就是以“最大堆长度设置应该是怎样?”这基本问题开始在深入研究的前让我们先复习下 Java 运行时中内存管理基础知识 ?牐燡VM 有片它自己管理内存空间对象存活(或消亡)所在那部分空间就叫做堆空间对象在堆空间中创建又由 JVM 垃圾收集器在区别时机围绕着堆空间对其进行迁移例如当对堆进行碎片整理(或者紧缩)时便需要移动对象对象在堆中也会消亡个死去对象也就是应用再也不能访问对象JVM 垃圾收集器寻找这些死去对象并回收这些对象所占用空间以便让这些空间能为新对象所用如果垃圾收集器无法进步通过回收死去对象来释放出空间那么就说这个堆已满 ?牐犚桓鲆崖?堆会引发问题如果堆是满而应用又试图创建更多对象JVM 就会向底层操作系统请求更多内存如果 JVM 得不到更多内存那么分配个新对象操作就会抛出 OutOfMemoryError 异常除非应用极其完善否则那就意味着该应用要崩溃 ?牐犇敲矗?对此我们能做点什么呢?大多数 JVM 都有个可选参数可用于指定堆所能达到最大长度如果堆已经达到了这个长度JVM 就不能再向操作系统请求更多内存在 Sun 和 IBM 最近提供 JVM 中该参数可通过 -Xmx 选项指定更老版本 JVM 使用个 -mx 选项现在大多数 JVM 还能理解这个选项应用服务器拥有它们自己配置参数可用于指定最大堆长度这些参数通常是通过 -Xmx 参数指定如果没有显式地使用 -Xmx 参数JVM 有个默认最大堆长度当然这个默认值是特定于供应商和版本Sun 1.4 JVM 提供最大堆长度默认值是 64 兆字节 ?牐犇敲矗?为了达到最佳性能最大堆长度应该为多少呢?您可能会认为“越大越好”这样话就可以避开 out-of-memory 并且可以尽量多地为应用分配所需内存然而事实证明如果堆太大话可能会产生大问题这是由操作系统工作方式所致现代操作系统有两种内存模式种是实(real)内存种是虚拟(virtual)内存虚拟内存可以制造出种假象让人认为拥有比实内存更多内存这是通过使用交换文件(swap file)中磁盘空间补充实内存来办到在这里交换文件充当种额外(overflow)内存操作系统可以调出当前使用不多将它们放在磁盘中直到需要时才重新调回内存这样便腾出了实内存(暂时地)以供他用通过这种方式可用内存便表现得比实内存更大从而允许更多或者更大进程得以运行相应代价就是那些在磁盘中页在需要时不得不重新调回内存这样就降慢了速度毕竟磁盘速度比起内存来要慢得多 ?牐犎绻?您允许堆比系统实内存(您机器上物理内存)还要大那么这个堆就要分页分页本身没什么问题——毕竟只是那些不经常使用页才要被分派到磁盘中但是当遇到垃圾收集时候由于要对整个堆进行扫描所有那些很少使用页又要返回到实内存中而其他页则需要被移出实内存送到磁盘上去以便为那些老页腾出空间这是个恶性循环被移出到磁盘页本身在堆中很可能使用得不多作为垃圾收集部分 垃圾收集器要扫描这些页其结果就是比起真正要做有用事来您需要花费更多时间来将页移进和移出内存 ?牐犂?圾收集常常是个应用瓶颈所在但是如果您还要让堆大到令操作系统不得不频繁地使用分页技术以便 JVM 能执行垃圾收集那么其结果就是次又次缓慢调页动作从而让应用慢如蠕动因此务必确保最大堆长度小于可用系统 RAM要为需要同时运行其他进程考虑尽量防止这种调页灾难发生

TAG: 改进 开发 性能
标签:
0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: