按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
■造型和实例:造型会耗去2 到 200 个单位的赋值时间。开销更大的甚至要求上溯继承(遗传)结构。其他
681
…………………………………………………………Page 683……………………………………………………………
高代价的操作会损失和恢复更低层结构的能力。
■图形:利用剪切技术,减少在repaint()中的工作量;倍增缓冲区,提高接收速度;同时利用图形压缩技
术,缩短下载时间。来自JavaWorld 的“Java Applets”以及来自 Sun 的“Performing Animation”是两个
很好的教程。请记着使用最贴切的命令。例如,为根据一系列点画一个多边形,和drawLine()相比,
drawPolygon()的速度要快得多。如必须画一条单像素粗细的直线,drawLine(x;y;x;y)的速度比
fillRect(x;y;1;1)快。
■使用API 类:尽量使用来自 Java API 的类,因为它们本身已针对机器的性能进行了优化。这是用Java 难
于达到的。比如在复制任意长度的一个数组时,arraryCopy()比使用循环的速度快得多。
■替换API 类:有些时候,API 类提供了比我们希望更多的功能,相应的执行时间也会增加。因此,可定做
特别的版本,让它做更少的事情,但可更快地运行。例如,假定一个应用程序需要一个容器来保存大量数
组。为加快执行速度,可将原来的 Vector (矢量)替换成更快的动态对象数组。
1。 其他建议
■将重复的常数计算移至关键循环之外——比如计算固定长度缓冲区的buffer。length 。
■static final (静态最终)常数有助于编译器优化程序。
■实现固定长度的循环。
■使用javac 的优化选项:…O。它通过内嵌static,final 以及private 方法,从而优化编译过的代码。注
意类的长度可能会增加(只对JDK 1。1 而言——更早的版本也许不能执行字节查证)。新型的“Just…in
time”(JIT)编译器会动态加速代码。
■尽可能地将计数减至 0——这使用了一个特殊的JVM 字节码。
D。4 参考资源
D。4。1 性能工具
'1' 运行于 Pentium Pro 200,Netscape 3。0,JDK 1。1。4 的MicroBenchmark (参见下面的参考资源'5')
'2' Sun的Java 文档页——JDK Java 解释器主题:
http://java。sun。/products/JDK/tools/win32/java。html
'3' Vladimir Bulatov的HyperProf
http://physics。orst。edu/~bulatov/HyperProf
'4' Greg White 的ProfileViewer
http://inetmi。/~gwhi/ProfileViewer/ProfileViewer。html
D。4。2 Web 站点
'5' 对于Java 代码的优化主题,最出色的在线参考资源是Jonathan Hardwick 的“Java Optimization”网
站:
http://cs。cmu。edu/~jch/java/optimization。html
“Java 优化工具”主页:
http://cs。cmu。edu/~jch/java/tools。html
以及“Java Microbenchmarks”(有一个45 秒钟的评测过程):
http://cs。cmu。edu/~jch/java/benchmarks。html
D。4。3 文章
'6' “Make Java fast:Optimize! How to get the greatest performanceout of your code through low
level optimizations in Java”(让Java 更快:优化!如何通过在Java 中的低级优化,使代码发挥最出色
的性能)。作者:Doug Bell。网址:
http://javaworld。/javaworld/jw…04…1997/jw…04…optimize。html
(含一个全面的性能评测程序片,有详尽注释)
'7' “Java Optimization Resources ”(Java 优化资源)
http://cs。cmu。edu/~jch/java/resources。html
'8' “Optimizing Java for Speed”(优化Java,提高速度):
http://cs。cmu。edu/~jch/java/speed。html
682
…………………………………………………………Page 684……………………………………………………………
'9' “An Empirical Study of FORTRAN Programs”(FORTRAN 程序实战解析)。作者:Donald Knuth。
1971 年出版。第 1卷,p。105…33,“软件——实践和练习”。
'10' “Building High…Performance Applications and Servers in Java:An Experiential Study”。作
者:Jimmy Nguyen,Michael Fraenkel,RichardRedpath,Binh Q。 Nguyen 以及Sandeep K。 Singhal。IBM
T。J。 Watson ResearchCenter;IBM Software Solutions。
http://ibm。/java/education/javahipr。html
D。4。4 Java 专业书籍
'11' 《Advanced Java ,Idioms,Pitfalls ,Styles; and Programming Tips》。作者:Chris Laffra。
Prentice Hall 1997 年出版(Java 1。0 )。第 11 章第20 小节。
D。4。5 一般书籍
'12' 《Data Structures and C Programs》(数据结构和C 程序)。作者:J。Van Wyk。Addison…Wesly
1998 年出版。
'13' 《Writing Efficient Programs》(编写有效的程序)。作者:Jon Bentley。Prentice Hall 1982 年
出版。特别参考p。110 和p。145…151。
'14' 《More Programming Pearls》(编程拾贝第二版)。作者:JonBentley。“Association for
puting Machinery”,1998 年2 月。
'15' 《Programming Pearls 》(编程拾贝)。作者:Jone Bentley。Addison…Wesley 1989 年出版。第2 部
分强调了常规的性能改善问题。 '16' 《Code plete:A Practical Handbook of Software
Construction》(完整代码索引:实用软件开发手册)。作者:Steve McConnell。Microsoft 出版社 1993
年出版,第 9 章。
'17' 《Object…Oriented System Development》(面向对象系统的开发)。作者:Champeaux,Lea 和
Faure。第25 章。
'18' 《The Art of Programming》(编程艺术)。作者:Donald Knuth。第1卷“基本算法第3 版”;第3
卷“排序和搜索第 2 版”。Addison…Wesley 出版。这是有关程序算法的一本百科全书。
'19' 《Algorithms in C:Fundammentals;Data Structures; Sorting;Searching》(C 算法:基础、数据结
构、排序、搜索)第3 版。作者:RobertSedgewick。Addison…Wesley 1997 年出版。作者是Knuth 的学生。
这是专门讨论几种语言的七个版本之一。对算法进行了深入浅出的解释。
683
…………………………………………………………Page 685……………………………………………………………
附录 E 关于垃圾收集的一些话
“很难相信Java 居然能和C++一样快,甚至还能更快一些。”
据我自己的实践,这种说法确实成立。然而,我也发现许多关于速度的怀疑都来自一些早期的实现方式。由
于这些方式并非特别有效,所以没有一个模型可供参考,不能解释Java 速度快的原因。
我之所以想到速度,部分原因是由于C++模型。C++将自己的主要精力放在编译期间“静态”发生的所有事情
上,所以程序的运行期版本非常短小和快速。C++也直接建立在C 模型的基础上(主要为了向后兼容),但有
时仅仅由于它在C 中能按特定的方式工作,所以也是C++中最方便的一种方法。最重要的一种情况是C 和C++
对内存的管理方式,它是某些人觉得Java 速度肯定慢的重要依据:在Java 中,所有对象都必须在内存
“堆”里创建。
而在C++中,对象是在堆栈中创建的。这样可达到更快的速度,因为当我们进入一个特定的作用域时,堆栈
指针会向下移动一个单位,为那个作用域内创建的、以堆栈为基础的所有对象分配存储空间。而当我们离开
作用域的时候(调用完毕所有局部构建器后),堆栈指针会向上移动一个单位。然而,在C++里创建“内存
堆”(Heap )对象通常会慢得多,因为它建立在C 的内存堆基础上。这种内存堆实际是一个大的内存池,要
求必须进行再循环(再生)。在C++里调用 delete 以后,释放的内存会在堆里留下一个洞,所以再调用new
的时候,存储分配机制必须进行某种形式的搜索,使对象的存储与堆内任何现成的洞相配,否则就会很快用
光堆的存储空间。之所以内存堆的分配会在C++里对性能造成如此重大的性能影响,对可用内存的搜索正是
一个重要的原因。所以创建基于堆栈的对象要快得多。
同样地,由于C++如此多的工作都在编译期间进行,所以必须考虑这方面的因素。但在 Java 的某些地方,事
情的发生却要显得“动态”得多,它会改变模型。创建对象的时候,垃圾收集器的使用对于提高对象创建的
速度产生了显著的影响。从表面上看,这种说法似乎有些奇怪——存储空间的释放会对存储空间的分配造成
影响,但它正是JVM 采取的重要手段之一,这意味着在 Java 中为堆对象分配存储空间几乎能达到与C++中在
堆栈里创建存储空间一样快的速度。
可将C++的堆(以及更慢的 Java 堆)想象成一个庭院,每个对象都拥有自己的一块地皮。在以后的某个时
间,这种“不动产”会被抛弃,而且必须再生。但在某些 JVM 里,Java 堆的工作方式却是颇有不同的。它更
象一条传送带:每次分配了一个新对象后,都会朝前移动。这意味着对象存储空间的分配可以达到非常快的
速度。“堆指针”简单地向前移至处女地,所以它与C++的堆栈分配方式几乎是完全相同的(当然,在数据
记录上会多花一些开销,但要比搜索存储空间快多了)。
现在,大家可能注意到了堆事实并非一条传送带。如按那种方式对待它,最终就要求进行大量的页交换(这
对性能的发挥会产生巨大干扰),这样终究会用光内存,出现内存分页错误。所以这儿必须采取一个技巧,
那就是著名的“垃圾收集器”。它在收集“垃圾”的同时,也负责压缩堆里的所有对象,将“堆指针”移至
尽可能靠近传送带开头的地方,远离发生(内存)分页错误的地点。垃圾收集器会重新安排所有东西,使其
成为一个高速、无限自由的堆模型,同时游刃有余地分配存储空间。
为真正掌握它的工作原理,我们首先需要理解不同垃圾收集器(GC)采取的工作方案。一种简单、但速度较
慢的GC 技术是引用计数。这意味着每个对象都包含了一个引用计数器。�