ï»??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲av日韩av天堂影片精品,国产亚洲色视频在线,久久亚洲2019中文字幕http://www.tkk7.com/jacky/category/6465.html技术创造个äºÞZ­h(hu¨¢n)å€? Technology Creates The Values Of Personzh-cnWed, 28 Feb 2007 02:47:28 GMTWed, 28 Feb 2007 02:47:28 GMT60Maximizing Java Performance on AIX: Part 5 - References and Conclusion[转]http://www.tkk7.com/jacky/articles/25875.htmljackyjackyThu, 29 Dec 2005 06:04:00 GMThttp://www.tkk7.com/jacky/articles/25875.htmlhttp://www.tkk7.com/jacky/comments/25875.htmlhttp://www.tkk7.com/jacky/articles/25875.html#Feedback0http://www.tkk7.com/jacky/comments/commentRss/25875.htmlhttp://www.tkk7.com/jacky/services/trackbacks/25875.html

Maximizing Java Performance on AIX: Part 5 - References and Conclusion

developerWorks
Document options
Set printer orientation to landscape mode

Print this page

Email this page

E-mail this page

Document options requiring JavaScript are not displayed


New site feature

Plan and design IT solutions with our new Architecture area


Rate this page

Help us improve this content


Level: Intermediate

Amit Mathur (amitmat@us.ibm.com), Senior Technical Consultant and Solutions Enablement Manager, IBM
Sumit Chawla (sumitc@us.ibm.com), IBM Certified IT Architect and Technical Lead, Java Enablement, IBM

17 May 2004

This is the conclusion of the 5-part series providing tips and techniques that are commonly used for tuning Javaâ„?applications for optimum performance on AIX]. We touch upon other interesting areas of Java performance tuning for AIX, look at a few case studies, and then end the series with a list of useful references.

Introduction

This is the conclusion of the 5-part series on Java Performance.The first article in the series laid the foundation for performance tuning, and parts 2, 3 and 4 looked at various bottlenecks that can affect a system's scalability and throughput. This article covers two important topics that were not covered previously, along with providing case studies and references.

A frequently asked question (FAQ) is about translating Sun-specific command-line switches to IBM-specific switches. Also, any serious performance tuning exercise, like benchmarks, cannot ignore system-wide tuning. We touch upon these topics briefly in the next section.

This is followed by a few case studies that attempt to illustrate how the tools and tips described in the series are applied to solve problems in the field. The emphasis is on understanding and learning how to use the tools and techniques mentioned in the series.

The article, and the series, concludes with a recap of useful references.



Back to top


Other Important Considerations

This section talks about translating Sun Java configuration to IBM Java configuration, and System-wide tuning for AIX applications. The scope of both of these topics is quite vast, so we only touch them briefly.

Translating Sun Java Switches

If you have an application that has been tuned for Sun Java, and you are attempting to migrate your application to AIX (or, for that matter, any platform running IBM Java), you may already have done the hard work. Understanding the application characteristics is half the battle. You can use the characteristics-based tuning tips explained in Part 2 and Part 3 based on the understanding obtained by the tuning exercise with Sun Java.

However, we frequently receive queries about how to translate specific Sun Java command-line switches to equivalent IBM Java command-line switches. These switches almost always correspond to Garbage Collection, as a well-tuned GC is essential to any Java-based application's performance. A mapping between Sun and IBM switches is difficult because of the difference in JVM architecture. The IBM Java does not contain a Generational Garbage Collector, and does not understand any command-line switches that start with -XX. IBM Java "Sovereign" architecture is not based on Sun HotSpot architecture as well. The easiest, and in most cases the quickest, way is to throw away all Sun-specific settings when running your application on IBM Platforms, and carrying out the fine-tuning as needed. But if you are curious about how some Sun switches map to IBM switches, read on.

The table below attempts to translate Sun Java GC command-line switches to equivalent IBM switches. This mapping is based on the functionality of Sun switches as described in the Sun-specific article "Tuning Garbage Collection with the 1.4.2 Java Virtual Machine". You should attempt to use this table only for the very specific purpose of locating an equivalent (or close) switch for IBM Java. This is not meant to replace the tuning exercise, as even heap size requirements can be quite different. For general GC tuning tips with IBM Java, as well as for information on these and other GC switches for IBM Java, please refer to Fine-tuning Java garbage collection performance. The creation of this table did not involve any performance-related testing, but was based entirely on the documented use of the Sun switches in the reference quoted above.

Sun Switch Equivalent IBM Switch Notes
-Xms, -Xmx -Xms, -Xmx These parameters, and their meaning, remain unchanged. You may still need to do heap sizing.
-XX:SurvivorRatio, -XX:NewSize,
-XX:MaxNewSize, -XX:NewRatio
None These switches can simply be removed, as they are for generational GC which doesn't apply for IBM Java.
-XX:MinHeapFreeRatio, -XX:MaxHeapFreeRatio -Xminf, -Xmaxf Heap expansion/shrinkage is controlled by other factors, not just these switches.
-Xverbose:gc, -XX:+PrintGCDetails -Xverbose:gc IBM Java verbosegc trace format is quite different from the Sun GC. More detailed tracing can be enabled as needed, but in most cases the default verbosegc traces are sufficient.
-XX:+UseParallelGC, -Xincgc, -XX:+AggressiveHeap None These are various types of Garbage Collectors supported by Sun. These do not apply to IBM Java.
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC -Xgcpolicy:optavgpause Concurrent Low-pause collector is close to the IBM Concurrent Mark in intent (but not necessarily in design).
-XX:+CMSParallelRemarkEnabled None Not applicable for IBM Java.
-XX:ParallelGCThreads -Xgcthreads It is not advisable to change this setting at least for IBM Java.
-Dsun.rmi.dgc.client.gcInterval, -Dsun.rmi.dgc.server.gcInterval -Dsun.rmi.dgc.client.gcInterval, -Dsun.rmi.dgc.server.gcInterval See NIO003 in Part 4.

As the above table demonstrates, translating the switches in most cases will involve simply discarding the Sun switches for IBM platforms. This makes the GC tuning exercise for IBM Java quite painless, while still providing superior performance.

System-wide tuning

Using AIX tools like schedo and vmo has a system-wide effect, so a thorough coverage of these tools is beyond the scope of the current series. See the Resources section for more information on these tools.

But for most multi-tiered applications and especially benchmarks, system-wide tuning is unavoidable. There are several excellent resources available for AIX performance tuning that you can consider. To get an idea of the kind of tuning normally required, you can look at actual published benchmarks. If you look at a recent SpecJBB 2000 result for IBM Java on AIX, say http://www.spec.org/osg/jbb2000/results/res2003q3/jbb2000-20030624-00194.html, the OS tunings are mentioned below:
Operating system tunings
  • SPINLOOPTIME=2000
  • vmo -r -o lgpg_regions=256 -o lgpg_size=16777216
  • setsched -S rr -P 40 -p $$
  • schedtune -t 400 -F 1
  • vmtune -S 1

Warning: These settings must not be applied without carefully understanding the consequences, as an improper use of these settings can actually worsen the system performance.

So what do the above settings do? Referring to AIX documentation, you can quickly get a better understanding of what each of these settings is doing. Let us examine each of these in turn.

The SPINLOOPTIME controls the number of times the system will retry a busy lock before yielding to another process. Since the default is 40, a higher value tells the system that it should try a little bit longer for the lock to be freed up. On multiprocessor systems, it results in better performance since a busy lock retry is cheaper than a process context switch.

The vmo line sets up the size and number of large pages. If you look at the Java command-line switches, you will see that -Xlp is being used. This enables Large page support in Java, which is described in more detail here. If you have a memory intensive application, you can experiment with large pages to see if it helps. More information on this topic is available in the SDK Guide accompanying Java.

The setsched line is actually a script, not an AIX command. It calls the thread_setsched kernel service to select fixed-priority round-robin scheduling, with a fixed priority of 40 for the Java process.

The schedtune command is also a script from AIX 5.2 onwards, that maps the passed parameters to the new schedo command. The above line is changing the time slice for fixed-priority threads to 400 ticks. It is also forcing the fixed priority threads to reside in the global run queue.

Finally, the vmtune command translates the call to an equivalent vmo call, and the above line enables pinning of shared memory segments.

So you can see that the system was switched to large pages and a fixed priority scheduler, to get record numbers with SpecJBB 2000 benchmark. Can you use these same settings in your application? Probably not, but you are now in a position to examine these commands and the scheduling policies, and experiment to suit your application characteristics. This is the next step in Performance tuning.



Back to top


Case Studies

In this section we look at a few examples, taken from actual issues handled by Java service team. These examples should give you a good idea of how to approach performance tuning, and how to use various tools to gather information that can be used for tuning exercise. Note that the cases for this section were not chosen based on how frequently the problem is encountered in the field. The emphasis is on understanding how to use the various tools and techniques discussed in the series to locate and correct performance issues.

Case 1: Bad application response time

The reported issue was that the Java-based application's response time was unacceptable. Using topas, and then with vmstat, it was seen that Java was the application consuming most CPU. Using tprof, the functions that showed up had GC-related terms in them (e.g. localMark, which is used in Mark phase), so this indicated a possible issue with Java heap sizing.

Looking at GC logs confirmed that the heap was expanding very often. This, combined with multiple allocation failures in quick succession and a very full heap, resulted in the Java application spending a lot of time just trying to locate a free chunk, not finding it, expanding the heap, and then satisfying only the current allocation request.

This was fixed by specifying a larger value for -Xmine, forcing the heap to grow faster (seeTip MEM003 in Part 3). The result was that a single expansion avoided multiple potential allocation failures.

The first step, using AIX tools, confirmed this to be a Java-related issue. The second step, guided by the fact that AIX tools indicated this to be a problem related with GC, could concentrate on GC logs directly. The third step used the available tuning parameters to break the unusual cycle that the application was getting into, allowing the excessive CPU time to be recovered.

Case 2: JVMPI to the rescue

Another interesting scenario was raised as a performance issue, with CPU being busy most of the time. Looking at verbosegc, we could see that a GC cycle was being called a bit too frequently, resulting in the application spending most of its time doing just GC.

The verbosegc traces showed that most of the GC activity was being caused due to multiple allocations of very large objects, roughly 10 MB or more in size. These were fragmenting the heap, making the GC cycles longer and thus affecting the performance. But looking at the verbosegc cycle, the customer could not say what these objects were.

The easiest way to locate the culprit would have been to analyze the heapdump using HeapRoots tool. But there was another twist to the situation: the large objects were not surviving the GC cycle. So the heapdump did not show any objects of such size.

This is a classic example of how profiling can be a very useful ally for locating and correcting problems in application sources. The Java Virtual Machine Profile Interface makes this problem trivial. For this particular example, we used a variation of the method described at Using JVMPI to Identify Large Memory Allocations, and were able to quickly identify the code that was doing this allocation.

Case 3: Unbounded growth

As the final case study for this article, we discuss a scenario that showed up looking like a simple sizing problem. An attempt was being made to scale the application to a 1000 users, and the application would run out of Java heap. Calculating the heap requirements based on the number of users, the heap size was increased from 1 GB to 1.5 GB.

But this triggered OOM errors not coming because of Java heap. The Java heap would show enough free space, but the application logs would show that an OOM occurred. Using svmon, it was seen that only around 4 segments, or 1 GB, were being used for native heap, and the fourth segment seemed to be almost empty (see "Balancing Memory" in "Getting more memory in AIX for your Java applications").

To dig further, the command-line switch -verbose:jni was added. The extra messages being printed as a result of this switch revealed that the global JNI reference pool was getting exhausted, which is a very rare thing to happen. The global JNI reference pool is large enough to ensure that most normal applications never run even close to exhausting it.

For some time we tried to work around the problem by increasing the number of JNI references (if you specify a higher -Xoss value, it increases the limit in a proportional manner). But this only delayed the inevitable, and the severe Java heap fragmentation caused by the large number of pinned JNI references did not help either.

A closer look at the application design revealed the true cause: an unbounded number of threads being created by the application. As the tests proceeded, the threads would wait for finalizers, and since finalizers are not predictable, there would be a large number of these threads waiting to release their JNI references. The only feasible solution in this case was to change the application code to correct these two problems. Once the application replaced the unbounded threads with a thread pool, and replaced finalizers wherever possible, the sizing work completed with flying colors.

This case shows how you can sometimes end up trying to hit a moving target. An issue reported as Java heap exhaustion eventually turned out to be a design problem. Balancing the Java and Native heaps is usually a critical part of performance tuning, but in this case it was not sufficient. Having so many tools and techniques at your disposal gives you a much broader picture, allowing you to make informed decisions about what to tune.



Back to top


Conclusion

This article concludes the series. We hope you find this series a valuable guide in maximizing the performance of your Java applications on AIX.

The authors thank Ashok Ambati, Rajesh Jeyapaul, Sharad Ballal, Roger Leuckie and Mark Bluemel for their input and advice on these articles. A special note of thanks goes to John Tesch, whose collection of information on AIX Java performance was a major source of inspiration to the series.



Back to top


Resources

Java on AIX
  • The IBM developer kits for AIX, Java technology edition, at http://www-106.ibm.com/developerworks/java/jdk/aix/service.html, contains links to all available Java releases on AIX. The SDK Guide for each version contains information relevant to the release and should be reviewed before you use that particular version. Another useful link is "Fix Info" link that, among other things, gives you a list of APARs you will need to apply to update all the filesets to the latest level.

  • The IBM developer kits - diagnosis documentation, at http://www-106.ibm.com/developerworks/java/jdk/diagnosis/, is a comprehensive document that provides thorough coverage of diagnostic capabilities of IBM Java. Best of all, it is platform-independent, so you can use it for all platforms that IBM Java runs on. A recent addition on this page is the "IBM Garbage Collection and Storage Allocation Techniques", a detailed look at how IBM Java implements Garbage Collection and is a must-read for anyone interested in finding out more about how IBM Java works.

  • Implementing Java on AIX (developerworks, March 2004), at http://www-106.ibm.com/developerworks/eserver/library/es-JavaOnAix_install.html, contains information you need to start using Java on AIX.

  • Since GC tuning is usually the most important part of performance tweaking, see Fine-tuning Java garbage collection performance (developerworks, January 2003), at http://www-106.ibm.com/developerworks/library/i-gctroub/, for a discussion of tweaking IBM Java heap characteristics. Note that this article is not AIX-specific. Parts 2 and 3 of the current series also look at some tips useful for GC tuning.

  • Getting more memory in AIX for your Java applications (developerworks, September, 2003), at http://www-106.ibm.com/developerworks/eserver/articles/aix4java1.html, provides information for heaps larger than 1 GB.
AIX
  • AIX 5L Performance Tools Handbook at http://publib-b.boulder.ibm.com/Redbooks.nsf/RedbookAbstracts/SG246039.html, covers each of the performance tools described in the current series (plus many more that are not). You will find practical advice on how to use a particular tool, examples of tool usage, and hints on how to interpret and use the information obtained using these tools.

  • Understanding IBM eServer pSeries Performance and Sizing at http://publib-b.boulder.ibm.com/Redbooks.nsf/RedbookAbstracts/SG244810.html, gives an overview of how IBM AIX-based systems are designed. If you are planning to do a benchmark exercise, this book is invaluable.

  • A series of three articles that talk about the changes to Performance tools in AIX 5.2 are Part 1 (developerworks, July 2003), Part 2 (developerworks, November 2003), and Part 3 (developerworks, January 2004. AIX 5.2 did a major overhaul of some of the familiar performance tools and this series covers the changes very well.

  • The AIX Performance PMR Data Collection Tools, described in Part 1, can be downloaded from ftp://ftp.software.ibm.com/aix/tools/perftools/perfpmr/

  • Checklist for isolating Java performance problems on AIX servers at http://www-106.ibm.com/developerworks/java/library/j-perf-checklist/


Back to top


About the authors

Amit Mathur works in the IBM Solutions Development group, working primarily with IBM ISVs in enablement/performance of their apps on IBM eServer platforms and providing self-sufficiency to ISVs and customers by providing education and articles on developer works. Amit has more than fourteen years' experience working in Leading software support and development in C/C++, Java and databases on UNIX and Linux platforms. He holds a Bachelor of Engineering degree in Electronics and Telecommunication from India. You can reach Amit at amitmat@us.ibm.com.


Sumit Chawla leads the Java Enablement initiative for IBM eServer (for AIX, Windows, and Linux platforms), assisting Independent Software Vendors for IBM Servers. Sumit has a Master of Science degree in Computer Science, with almost 10 years of experience in the IT industry, and is certified by IBM as an Application Architect. He is a frequent contributor to the developerWorks eServer zone. You can contact him at sumitc@us.ibm.com.



jacky 2005-12-29 14:04 å‘表评论
]]>
Java ç†è®ºä¸Žå®žè·? JVM 1.4.1 中的垃圾攉™›†[转]http://www.tkk7.com/jacky/articles/25874.htmljackyjackyThu, 29 Dec 2005 05:59:00 GMThttp://www.tkk7.com/jacky/articles/25874.htmlhttp://www.tkk7.com/jacky/comments/25874.htmlhttp://www.tkk7.com/jacky/articles/25874.html#Feedback0http://www.tkk7.com/jacky/comments/commentRss/25874.htmlhttp://www.tkk7.com/jacky/services/trackbacks/25874.html

Java ç†è®ºä¸Žå®žè·? JVM 1.4.1 中的垃圾攉™›†

分代垃圾攉™›†å’Œåƈå‘垃圾收é›?/P> developerWorks
文档选项
ž®†æ­¤™åµä½œä¸ºç”µå­é‚®ä»¶å‘é€?src="http://www.ibm.com/i/v14/icons/em.gif"

ž®†æ­¤™åµä½œä¸ºç”µå­é‚®ä»¶å‘é€?/FONT>

未显½Cºéœ€è¦?JavaScript 的文档选项


å¯ÒŽ(gu¨©)­¤™å늚„评ä­h(hu¨¢n)

帮助我们改进˜q™äº›å†…容


¾U§åˆ«: åˆçñ”

Brian Goetz, 首席™åùN—®, Quiotix Corp

2003 òq?12 æœ?01 æ—?/P>

在上月的 Java ç†è®ºä¸Žå®žè·?/I>中,专æ ä½œå®¶ Brian Goetz 回顾了垃圾收集的基本½Ž—法。本月,他进一步探è®?JVM 1.4.1 是如何实际处ç†åžƒåœ¾æ”¶é›†çš„åQŒåŒ…括一些针对多处ç†å™¨ç³»¾lŸçš„æ–°åžƒåœ¾æ”¶é›†é€‰é¡¹ã€‚请在本文对应的 讨论论å›ä¸Šä¸Žä½œè€…åŠå…¶ä»–读者分享æ?zh¨¨n)¨å¯Ò?gu¨©)œ¬æ–‡çš„心得åQˆæ?zh¨¨n)¨ä¹Ÿå¯ä»¥å•å‡ÀL–‡ç« é¡¶éƒ¨æˆ–底部çš?讨论æ¥è®¿é—®è¯¥è®ºå›åQ‰ã€?

上个æœ?/FONT>åQŒæˆ‘们分æžäº†å¼•用计数ã€å¤åˆ¶ã€æ ‡è®?清除和标è®?整熘q™äº›¾l典的垃圾收集技术。其中æ¯ä¸€¿U方法在特定æ¡äšg下都有其优点和缺ç‚V€‚例如,当有很多对象æˆäؓ垃圾æ—Óž¼Œå¤åˆ¶å¯ä»¥åšå¾—很好åQŒä½†æ˜¯æœ‰è®¸å¤šé•¿å¯¿å¯¹è±¡æ—¶å®ƒ?y¨­u)®±å˜å¾—很¾pŸï¼ˆè¦åå¤å¤åˆ¶å®ƒä»¬ï¼‰ã€‚相å,标记-æ•´ç†å¯¹äºŽé•¿å¯¿å¯¹è±¡å¯ä»¥åšå¾—很好åQˆåªå¤åˆ¶ä¸€‹Æ¡ï¼‰åQŒä½†æ˜¯å½“有许多短寿对象时ž®±æ²¡æœ‰é‚£ä¹ˆå¥½äº†ã€‚JVM 1.2 åŠä»¥åŽç‰ˆæœ¬ä‹É用的技术称ä¸?分代垃圾攉™›†åQˆgenerational garbage collectionåQ?/I>,它结åˆäº†˜q™ä¸¤¿U技术以¾l“åˆäºŒè€…的长处åQŒç»“果就是对象分é…开销éžå¸¸ž®ã€?

è€å¯¹è±¡å’Œòq´è½»å¯¹è±¡

在ä“Q何一个应用程åºå †ä¸­ï¼Œä¸€äº›å¯¹è±¡åœ¨åˆ›å¾åŽå¾ˆå¿«å°±æˆäؓ垃圾åQŒå¦ä¸€äº›åˆ™åœ¨ç¨‹åºçš„æ•´ä¸ª˜qè¡ŒæœŸé—´ä¸€ç›´ä¿æŒç”Ÿå­˜ã€‚ç»éªŒåˆ†æžè¡¨æ˜Žï¼Œå¯¹äºŽå¤§å¤šæ•°é¢å‘对象的语言åQŒåŒ…æ‹?Java 语言åQŒç»å¤§å¤šæ•°å¯¹è±¡â€•―å¯ä»¥å¤šè¾?98%åQˆè¿™å–决于æ?zh¨¨n)¨å¯¹å¹´è½Õd¯¹è±¡çš„è¡¡é‡æ ‡å‡†åQ‰æ˜¯åœ¨å¹´è½Èš„æ—¶å€™æ­»äº¡çš„。å¯ä»¥ç”¨æ—‰™’Ÿ¿U’æ•°ã€å¯¹è±¡åˆ†é…以åŽï¿½h内存½Ž¡ç†å­ç³»¾lŸåˆ†é…çš„æ€Õd­—节或者对象分é…厾l历的垃圾收集的‹Æ¡æ•°æ¥è®¡½Ž—å¯¹è±¡çš„å¯¿å‘½ã€‚ä½†æ˜¯ä¸½Ž¡æ?zh¨¨n)¨å¦‚何计é‡åQŒåˆ†æžè¡¨æ˜Žäº†åŒä¸€ä»¶äº‹â€•―大多数对象是在òq´è½»çš„æ—¶å€™æ­»äº¡çš„。大多数对象在年è½ÀL—¶æ­ÖMº¡˜q™ä¸€äº‹å®žå¯¹äºŽæ”‰™›†å™¨çš„选择很有æ„义。特别是åQŒå½“大多数对象在òq´è½»æ—¶æ­»äº¡æ—¶åQŒå¤åˆ¶æ”¶é›†å™¨å¯ä»¥æ‰§è¡Œå¾—相当好åQŒå› ä¸ºå¤åˆ¶æ”¶é›†å™¨å®Œå…¨ä¸è®¿é—®æ­»äº¡çš„对象åQŒå®ƒä»¬åªæ˜¯å°†‹zÈš„对象å¤åˆ¶åˆ°å¦ä¸€ä¸ªå †åŒºåŸŸä¸­ï¼Œç„¶åŽä¸€‹Æ¡æ€§æ”¶å›žæ‰€æœ‰çš„剩余½Iºé—´ã€?/P>

那些¾l历˜q‡ç¬¬ä¸€‹Æ¡åžƒåœ¾æ”¶é›†åŽä»èƒ½ç”Ÿå­˜çš„对象,很大部分会æˆä¸ºé•¿å¯¿çš„æˆ–者永久的对象。根æ®çŸ­å¯¿å¯¹è±¡å’Œé•¿å¯¿å¯¹è±¡çš„æØœåˆæ¯”例,ä¸åŒåžƒåœ¾æ”‰™›†½{–略的性能会有éžå¸¸å¤§çš„差别。当大多数对象在òq´è½»æ—¶æ­»äº¡æ—¶åQŒå¤åˆ¶æ”¶é›†å™¨å¯ä»¥å·¥ä½œå¾—å¾ˆå¥½ï¼Œå› äØ“òq´è½»æ—¶æ­»äº¡çš„对象永远ä¸éœ€è¦å¤åˆ¶ã€‚丘q‡ï¼Œå¤åˆ¶æ”‰™›†å™¨å¤„ç†é•¿å¯¿å¯¹è±¡å´å¾ˆç³Ÿ¾p•,它è¦ä»Žä¸€ä¸ªåнIºé—´å‘å¦ä¸€ä¸ªåнIºé—´å夿¥å›žå¤åˆ¶˜q™äº›å¯¹è±¡ã€‚相å,标记-æ•´ç†æ”‰™›†å™¨å¯¹äºŽé•¿å¯¿å¯¹è±¡å¯ä»¥å·¥ä½œå¾—很好åQŒå› ä¸ºé•¿å¯¿å¯¹è±¡è¶‹å‘于沉在堆的底部åQŒä»Žè€Œä¸ç”¨å†å¤åˆ¶ã€‚丘q‡ï¼Œæ ‡è®°-清除和标è®?ç†æ•´æ”‰™›†å™¨è¦åšå¾ˆå¤šé¢å¤–çš„åˆ†æžæ­ÖMº¡å¯¹è±¡çš„å·¥ä½œï¼Œå› äØ“åœ¨æ¸…é™¤é˜¶ŒDµå®ƒä»¬å¿…™åÕdˆ†æžå †ä¸­çš„æ¯ä¸€ä¸ªå¯¹è±¡ã€?/P>

回页�/FONT>


分代攉™›†

分代攉™›†å™?generializational collector)ž®†å †åˆ†äؓ多个代。在òq´è½»çš„代中创建对象,满èƒöæŸäº›æå‡æ ‡å‡†çš„对象,如ç»åŽ†äº†ç‰¹å®š‹Æ¡æ•°åžƒåœ¾æ”‰™›†çš„对象,ž®†è¢«æå‡åˆîC¸‹ä¸€æ›´è€çš„代。分代收集器对ä¸åŒçš„代å¯ä»¥è‡ªç”׃‹É用ä¸åŒçš„æ”‰™›†½{–ç•¥åQŒå¯¹å„代分别˜q›è¡Œåžƒåœ¾æ”‰™›†ã€?/P>

ž®çš„æ”‰™›†

分代攉™›†çš„一个优ç‚ÒŽ(gu¨©)˜¯å®ƒä¸åŒæ—¶æ”‰™›†æ‰€æœ‰çš„代,因此å¯ä»¥ä½¿åžƒåœ¾æ”¶é›†æš‚åœæ›´çŸ­ã€‚当分é…器ä¸èƒ½æ»¡­‘›_ˆ†é…请求时åQŒå®ƒé¦–先触å‘一ä¸?ž®çš„æ”‰™›†åQˆminor collectionåQ?/I>åQŒå®ƒåªæ”¶é›†æœ€òq´è½»çš„代。因为年è½ÖM»£ä¸­çš„è®¸å¤šå¯¹è±¡å·²ç»æ­ÖMº¡åQŒå¤åˆ¶æ”¶é›†å™¨å®Œå…¨ä¸ç”¨åˆ†æžæ­ÖMº¡çš„对象,所以å°çš„æ”¶é›†çš„æš‚åœå¯ä»¥ç›¸å½“çŸ­åÆˆé€šå¸¸å¯ä»¥å›žæ”¶å¤§é‡çš„å †½Iºé—´ã€‚如果å°çš„æ”¶é›†é‡Šæ”¾äº†­‘›_¤Ÿçš„å †½Iºé—´åQŒé‚£ä¹ˆç”¨æˆïL¨‹åºå°±å¯ä»¥ç«‹å³æ¢å¤ã€‚如果它ä¸èƒ½é‡Šæ”¾­‘›_¤Ÿçš„å †½Iºé—´åQŒé‚£ä¹ˆå®ƒ?y¨­u)®Þq‘ô¾l­æ”¶é›†ä¸Šä¸€ä»£ï¼Œç›´åˆ°å›žæ”¶äº†èƒö够的内存。(在垃圾收集器˜q›è¡Œäº†å…¨éƒ¨æ”¶é›†ä»¥åŽä»ä¸èƒ½å›žæ”¶­‘›_¤Ÿçš„内存时åQŒå®ƒ?y¨­u)®†æ‰©å±•堆或者抛å‡?OutOfMemoryError åQ‰ã€?

代间引用

跟踪垃圾攉™›†å™¨ï¼Œå¦‚å¤åˆ¶ã€æ ‡è®?清除和标è®?整熽{‰åžƒåœ¾æ”¶é›†å™¨,都是从根集(root setåQ‰å¼€å§‹æ‰«æï¼Œé历对象间的引用åQŒç›´åˆ°è®¿é—®äº†æ‰€æœ‰æ´»çš„对象ã€?/P>

分代跟踪攉™›†å™¨ä»Žæ šw›†å¼€å§‹ï¼Œä½†æ˜¯òq¶ä¸éåŽ†æŒ‡å‘æ›´è€ä¸€ä»£ä¸­å¯¹è±¡çš„引用,˜q™å‡ž®‘了è¦è·Ÿítªçš„对象囄¡š„大å°ã€‚但是这也带æ¥ä¸€ä¸ªé—®é¢˜â€•―如果更è€ä¸€ä»£ä¸­çš„对象引用一个ä¸èƒ½é€šè¿‡ä»Žæ ¹å¼€å§‹çš„æ‰€æœ‰å…¶ä»–引用链到达的更òq´è½»çš„对象该怎么办?

ä¸ÞZº†è§£å†³˜q™ä¸ªé—®é¢˜åQŒåˆ†ä»£æ”¶é›†å™¨å¿…须昑ּ地跟ítªä»Žè€å¯¹è±¡åˆ°òq´è½»å¯¹è±¡çš„å¼•ç”¨åÆˆž®†è¿™äº›è€åˆ°òq´è½»çš„引用加入到ž®çš„æ”‰™›†çš„æ ¹é›†ä¸­ã€‚有两ç§åˆ›å¾ä»Žè€å¯¹è±¡åˆ°òq´è½»å¯¹è±¡çš„引用的æ–ÒŽ(gu¨©)³•。è¦ä¹ˆæ˜¯ž®†è€å¯¹è±¡ä¸­åŒ…å«çš„å¼•ç”¨ä¿®æ”¹äØ“æŒ‡å‘òq´è½»å¯¹è±¡åQŒè¦ä¹ˆæ˜¯ž®†å¼•用其他年è½Õd¯¹è±¡çš„òq´è½»å¯¹è±¡æå‡ä¸ºæ›´è€çš„一代ã€?/P>

跟踪代间引用

ä¸ç®¡ä¸€ä¸ªè€åˆ°òq´è½»çš„引用是通过æå‡˜q˜æ˜¯æŒ‡é’ˆä¿®æ”¹åˆ›å¾çš„,垃圾攉™›†å™¨åœ¨˜q›è¡Œž®çš„æ”‰™›†æ—‰™œ€è¦æœ‰å…¨éƒ¨è€åˆ°òq´è½»çš„引用。åšåˆ°è¿™ä¸€ç‚¹çš„一¿U方法是跟踪è€çš„代,但是˜q™æ˜¾ç„¶æœ‰å¾ˆå¤§çš„开销。更好的一¿U方法是¾U¿æ€§æ‰«æè€çš„代以查找对年è½Õd¯¹è±¡çš„引用。这¿U方法比跟踪更快òq¶æœ‰æ›´å¥½çš„区域性(localityåQ‰ï¼Œä½†æ˜¯ä»ç„¶æœ‰å¾ˆå¤§çš„工作é‡ã€?/P>

赋值函敎ͼˆmutatoråQ‰å’Œåžƒåœ¾æ”‰™›†å™¨å¯ä»¥å…±åŒå·¥ä½œä»¥åœ¨åˆ›å»ø™€åˆ°òq´è½»çš„引用时¾l´æŠ¤å®ƒä»¬çš„完整列表。当对象æå‡ä¸ºæ›´è€ä¸€ä»£æ—¶åQŒåžƒåœ¾æ”¶é›†å™¨å¯ä»¥è®°å½•所有由于这¿Uæå‡è€Œåˆ›å»ºçš„è€åˆ°òq´è½»çš„引用,˜q™æ ·ž®±åªéœ€è¦è·Ÿítªç”±æŒ‡é’ˆä¿®æ”¹æ‰€åˆ›å¾çš„代间引用ã€?/P>

垃圾攉™›†å™¨å¯ä»¥æœ‰å‡ ç§æ–ÒŽ(gu¨©)³•跟踪ç”׃ºŽä¿®æ”¹çŽ°æœ‰å¯¹è±¡ä¸­çš„å¼•ç”¨è€Œäñ”生的è€åˆ°òq´è½»çš„引用。它å¯ä»¥ä½¿ç”¨åœ¨å¼•ç”¨è®¡æ•°æ”¶é›†å™¨ä¸­ç»´æŠ¤å¼•ç”¨è®¡æ•°çš„åŒæ ·æ–ÒŽ(gu¨©)³•åQˆç¼–译器å¯ä»¥ç”Ÿæˆå›´ç»•指针赋值的附加指ä×oåQ‰è·Ÿítªå®ƒä»¬ï¼Œä¹Ÿå¯ä»¥åœ¨è€ä¸€ä»£å †ä¸Šä‹Éç”¨è™šæ‹Ÿå†…å­˜ä¿æŠ¤ä»¥æ•获å‘è€å¯¹è±¡çš„写入。å¦ä¸€¿Uå¯èƒ½æ›´æœ‰æ•ˆçš„虚拟内存方法是在è€ä¸€ä»£å †ä¸­ä‹É用页修改è„ä½åQˆpage modification dirty bitåQ‰ï¼Œä»¥ç¡®å®šäؓ扑ֈ°åŒ…å«è€åˆ°òq´è½»æŒ‡é’ˆçš„å¯¹è±¡æ—¶è¦æ‰«æçš„å—ã€?/P>

ç”¨ä¸€ç‚¹å°æŠ€å·§ï¼Œž®±å¯ä»¥é¿å…è·Ÿítªæ¯ä¸€ä¸ªæŒ‡é’ˆä¿®æ”¹åƈ‹‚€æŸ¥å®ƒæ˜¯å¦è·¨è¶Šä»£è¾¹ç•Œçš„开销。例如,ä¸éœ€è¦è·Ÿítªé’ˆå¯ÒŽ(gu¨©)œ¬åœ°æˆ–è€…é™æ€å˜é‡çš„存储åQŒå› ä¸ºå®ƒä»¬å·²¾l是栚w›†çš„一部分了。也å¯ä»¥é¿å…跟踪存储在æŸäº›æž„造函æ•îC¸­çš„æŒ‡é’ˆï¼Œ˜q™äº›æž„造函数åªç”¨äºŽåˆå§‹åŒ–新建对象的字段åQˆå³æ‰€è°?åˆå§‹åŒ–存储(initializing storesåQ?/I>åQ‰ï¼Œå› äØ“åQˆå‡ ä¹Žï¼‰æ‰€æœ‰å¯¹è±¡éƒ½æ˜¯åˆ†é…到òq´è½»ä»£ä¸­ã€‚ä¸½Ž¡æ˜¯ä»€ä¹ˆæƒ…å†µï¼Œ˜q行库都必须¾l´æŠ¤ä¸€ä¸ªè€å¯¹è±¡åˆ°òq´è½»å¯¹è±¡çš„引用集òq¶åœ¨æ”‰™›†òq´è½»ä»£æ—¶ž®†è¿™äº›å¼•用添加到栚w›†ä¸­ã€?

在图 1 中,½Ž­å¤´è¡¨ç¤ºå †ä¸­å¯¹è±¡é—´çš„引用。红色箭头表½Cºå¿…™åÀL·»åŠ åˆ°æ šw›†ä¸­ä¾›ž®çš„æ”‰™›†ä½¿ç”¨çš„è€åˆ°òq´è½»çš„引用。è“色箭头表½CÞZ»Žæ šw›†æˆ–者年è½ÖM»£åˆ°è€å¯¹è±¡çš„引用åQŒåœ¨åªæ”¶é›†å¹´è½ÖM»£æ—¶ä¸éœ€è¦è·Ÿítªå®ƒä»¬ã€?/P>
�1. 代间引用
代间引用

å¡ç‰‡æ ‡è®°

Sun JDK 使用一¿Uç§°ä¸?å¡ç‰‡æ ‡è®°åQˆcard markingåQ?/I>½Ž—法的改˜q›ç®—法以标识对è€ä¸€ä»£å¯¹è±¡çš„字段中包å«çš„æŒ‡é’ˆçš„ä¿®æ”V€‚在˜q™ç§æ–ÒŽ(gu¨©)³•中,堆分ä¸ÞZ¸€¾l?å¡ç‰‡åQŒæ¯ä¸ªå¡ç‰‡ä¸€èˆ¬éƒ½ž®äºŽä¸€ä¸ªå†…存页。JVM ¾l´æŠ¤ç€ä¸€ä¸ªå¡ç‰‡æ˜ ž®„,对应于堆中的æ¯ä¸€ä¸ªå¡ç‰‡éƒ½æœ‰ä¸€ä¸ªä½åQˆåœ¨æŸäº›å®žçŽ°ä¸­æ˜¯ä¸€ä¸ªå­—èŠ‚ï¼‰ã€‚æ¯‹Æ¡ä¿®æ”¹å †ä¸­å¯¹è±¡ä¸­çš„æŒ‡é’ˆå­—ŒD‰|—¶åQŒå°±åœ¨å¡ç‰‡æ˜ ž®„中讄¡½®å¯¹åº”那张å¡ç‰‡çš„相应ä½ã€‚在垃圾攉™›†æ—Óž¼Œž®±å¯¹ä¸Žè€ä¸€ä»£ä¸­å¡ç‰‡ç›¸å…³è”的标记ä½è¿›è¡Œæ£€æŸ¥ï¼Œå¯¹è„çš„å¡ç‰‡æ‰«æä»¥å¯ÀL‰¾å¯¹å¹´è½ÖM»£æœ‰å¼•ç”¨çš„å¯¹è±¡ã€‚ç„¶åŽæ¸…除标è®îC½ã€‚å¡ç‰‡æ ‡è®°æœ‰å‡ é¡¹å¼€é”€â€•―å¡ç‰‡æ˜ ž®„所需的é¢å¤–空间ã€å¯¹æ¯ä¸€ä¸ªæŒ‡é’ˆå­˜å‚¨æ‰€åšçš„é¢å¤–工作åQŒä»¥åŠåœ¨åžƒåœ¾æ”‰™›†æ—¶åšçš„é¢å¤–工作。对æ¯ä¸€ä¸ªéžåˆå§‹åŒ–堆指针存储åQŒå¡ç‰‡æ ‡è®°ç®—法å¯ä»¥åªå¢žåŠ ä¸¤åˆ°ä¸‰ä¸ªæœºå™¨æŒ‡ä×oåQŒåÆˆè¦æ±‚在å°çš„æ”¶é›†æ—¶å¯ÒŽ(gu¨©)‰€æœ‰è„å¡ç‰‡ä¸Šçš„对象˜q›è¡Œæ‰«æã€?



回页�/FONT>


JDK 1.4.1 默认攉™›†å™?/FONT>

在默认情况下åQŒJDK 1.4.1 ž®†å †åˆ†äؓ两部分,一个年è½Èš„代和一个è€çš„代(实际上,˜q˜æœ‰½W¬ä¸‰éƒ¨åˆ†â€•―永久空é—ß_¼Œå®ƒç”¨äºŽå­˜å‚¨è£…载的¾cÕd’Œæ–ÒŽ(gu¨©)³•对象åQ‰ã€‚借助于å¤åˆ¶æ”¶é›†å™¨åQŒå¹´è½Èš„代åˆåˆ†äؓ一个创建空é—ß_¼ˆé€šå¸¸¿UîCØ“ EdenåQ‰å’Œä¸¤ä¸ªç”Ÿå­˜åŠç©ºé—´ã€?

è€çš„代ä‹É用标è®?æ•´ç†æ”‰™›†å™¨ã€‚对象在¾l历了几‹Æ¡å¤åˆ¶åŽæå‡åˆ°è€çš„代。å°çš„æ”¶é›†å°†‹zÈš„对象ä»?Eden 和一个生存劽Iºé—´å¤åˆ¶åˆ°å¦ä¸€ä¸ªç”Ÿå­˜åнIºé—´åQŒåƈå¯èƒ½æå‡ä¸€äº›å¯¹è±¡åˆ°è€çš„代。大的收集(major collectionåQ‰æ—¢ä¼šæ”¶é›†å¹´è½Èš„代,也会攉™›†è€çš„代ã€?System.gc() æ–ÒŽ(gu¨©)³•æ€ÀL˜¯è§¦å‘一个大的收集,˜q™å°±æ˜¯åº”该尽é‡å°‘用(如果ä¸èƒ½å®Œå…¨ä¸ç”¨çš„è¯åQ?System.gc() 的原因之一åQŒå› ä¸ºå¤§çš„æ”¶é›†è¦æ¯”å°çš„æ”¶é›†èŠ±è´šw•¿å¾—多的时间。没有办法以¾~–程方å¼è§¦å‘ž®çš„æ”‰™›†ã€?

其他攉™›†é€‰é¡¹

除了默认情况下ä‹É用的å¤åˆ¶æ”‰™›†å™¨å’Œæ ‡è®°-æ•´ç†æ”‰™›†å™¨ï¼ŒJDK 1.4.1 ˜q˜åŒ…å«å…¶ä»–å››¿U垃圾收集算法,æ¯ä¸€¿U适用于ä¸åŒçš„目的。JDK 1.4.1 包å«ä¸€ä¸ªå¢žé‡æ”¶é›†å™¨åQˆè‡ª JDK 1.2 ž®±å·²¾l出çŽîCº†åQ‰å’Œä¸‰ç§åœ¨å¤šå¤„ç†å™¨ç³»¾lŸä¸­˜q›è¡Œæ›´æœ‰æ•ˆæ”¶é›†çš„æ–°æ”¶é›†å™¨â€•â€•åÆˆè¡Œå¤åˆ¶æ”¶é›†å™¨ã€åƈ行清除(scavengingåQ‰æ”¶é›†å™¨å’ŒåÆˆå‘æ ‡è®?清除攉™›†å™¨ã€‚这些新攉™›†å™¨æ˜¯ä¸ÞZº†è§£å†³åœ¨å¤šå¤„ç†å™¨ç³»¾lŸä¸­åžƒåœ¾æ”‰™›†å™¨æˆä¸ÞZŽ×¾~©æ€§ç“¶é¢ˆè¿™ä¸€é—®é¢˜çš„。图 2 昄¡¤ºäº†åœ¨ä»€ä¹ˆæ—¶å€™é€‰æ‹©å¤‡ç”¨æ”‰™›†é€‰é¡¹çš„æŒ‡å¯¹{€?/P>
å›?2. 1.4.1 垃圾攉™›†é€‰é¡¹åQˆFolgmann IT-Consulting æä¾›åQ?
垃圾攉™›†é€‰é¡¹

å¢žé‡æ”‰™›†

å¢žé‡æ”‰™›†é€‰é¡¹è‡?1.2 èµ·å°±æˆäØ“ JDK çš„ä¸€éƒ¨åˆ†ã€‚å¢žé‡æ”¶é›†å‡ž®‘了垃圾攉™›†æš‚åœåQŒä»¥ç‰ºç‰²åžå能力ä¸ÞZ»£ä»øP¼Œ˜q™ä‹É它åªåœ¨æ›´çŸ­çš„æ”‰™›†æš‚åœéžå¸¸é‡è¦æ—¶æ‰å€¼å¾—考虑åQŒå¦‚接近实时的系¾lŸã€?/P>

Train½Ž—法æ˜?JDK ç”¨äºŽå¢žé‡æ”‰™›†çš„算法,它在堆中è€çš„代和òq´è½»çš„代之间创å¾ä¸€ä¸ªæ–°åŒºåŸŸã€‚这些堆区域划分为“ç«è½¦ï¼ˆtrainåQ‰â€ï¼Œæ¯ä¸ªç«èžRåˆåˆ†ä¸ÞZ¸€¾pÕdˆ—的“èžR厢(caråQ‰â€ã€‚æ¯ä¸ªèžR厢å¯ä»¥åˆ†åˆ«æ”¶é›†ã€‚结果,æ¯ä¸ªç«èžR车厢¾l„æˆå•独的一代,˜q™æ„味ç€ä¸ä½†è¦è·Ÿítªè€åˆ°òq´è½»çš„引用,而且˜q˜è¦è·Ÿè¸ªä»Žè€çš„ç«èžR到年è½Èš„ç«èžR以åŠè€çš„车厢到年è½Èš„è½¦åŽ¢çš„å¼•ç”¨ã€‚è¿™ä¸ø™µ‹å€¼å‡½æ•ŽÍ¼ˆmutatoråQ‰å’Œåžƒåœ¾æ”‰™›†å™¨å¸¦æ¥äº†å¤§é‡çš„é¢å¤–工作,但是å¯ä»¥å¾—到更短的收集暂åœã€?

òq¶è¡Œæ”‰™›†å™¨å’Œòq¶å‘攉™›†å™?/STRONG>

JDK 1.4.1 ä¸­æ–°çš„æ”¶é›†å™¨éƒ½æ˜¯ä¸ø™§£å†›_¤šå¤„ç†å™¨ç³»¾lŸä¸­åžƒåœ¾æ”‰™›†å™¨çš„问题而设计的。因为大多数垃圾攉™›†½Ž—法会在一ŒD‰|—¶é—´é‡Œä½¿ç³»¾lŸåœæ­¢ï¼Œå•线½E‹çš„æ”‰™›†å™¨å¾ˆå¿«ä¼šæˆäØ“ä¼¸ç¾ƒæ€§ç“¶é¢ˆï¼Œå› äØ“åœ¨åžƒåœ¾æ”¶é›†å™¨ž®†ç”¨æˆïL¨‹åºçº¿½E‹æŒ‚èµäh—¶åQŒé™¤äº†ä¸€ä¸ªå¤„ç†å™¨ä¹‹å¤–åQŒå…¶ä»–的处ç†å™¨éƒ½æ˜¯ç©ºé—²çš„。新攉™›†å™¨ä¸­çš„ä¸¤ä¸ªâ€•â€•åÆˆè¡Œå¤åˆ¶æ”¶é›†å™¨å’ŒåÆˆå‘æ ‡è®?清除攉™›†å™¨â€•â€•è®¾è®¡äØ“å‡å°‘攉™›†æš‚åœæ—‰™—´ã€‚å¦ä¸€ä¸ªæ˜¯òq¶è¡Œæ¸…除攉™›†å™¨ï¼Œå®ƒæ˜¯ä¸ºåœ¨å¤§å †ä¸Šçš„æ›´é«˜åžå能力而设计的ã€?/P>

òq¶è¡Œå¤åˆ¶æ”‰™›†å™¨ç”¨ JVM 选项 -XX:+UseParNewGC å¯ç”¨åQŒæ˜¯ä¸€ä¸ªå¹´è½ÖM»£å¤åˆ¶æ”‰™›†å™¨ï¼Œå®ƒå°†åžƒåœ¾æ”‰™›†çš„工作分ä¸ÞZ¸Ž CPU æ•°é‡ä¸€æ ·å¤šçš„线½E‹ã€‚åÆˆå‘æ ‡è®?清除攉™›†å™¨ç”± -XX:+UseConcMarkSweepGC 选项å¯ç”¨åQŒå®ƒæ˜¯ä¸€ä¸ªè€ä»£æ ‡è®°-清除攉™›†å™¨ï¼Œå®ƒåœ¨åˆå§‹æ ‡è®°é˜¶æ®µåQˆåŠåœ¨ä»¥åŽæš‚çŸ­é‡æ–°æ ‡è®°é˜¶ŒDµï¼‰æš‚çŸ­åœ°åœæ­¢æ•´ä¸ªç³»¾lŸï¼Œç„¶åŽæ¢å¤ç”¨æˆ·½E‹åºåQŒåŒæ—¶åžƒåœ¾æ”¶é›†å™¨¾U¿ç¨‹ä¸Žç”¨æˆïL¨‹åºåƈå‘åœ°æ‰§è¡Œã€‚åÆˆè¡Œå¤åˆ¶æ”¶é›†å™¨å’ŒåÆˆå‘æ ‡è®?清除攉™›†å™¨åŸºæœ¬ä¸Šæ˜¯é»˜è®¤çš„å¤åˆ¶æ”‰™›†å™¨å’Œæ ‡è®°-æ•´ç†æ”‰™›†å™¨çš„òq¶å‘版本。由 -XX:+UseParallelGC å¯ç”¨çš„åÆˆè¡Œæ¸…é™¤æ”¶é›†å™¨æ˜¯å¹´è½ÖM»£æ”‰™›†å™¨ï¼Œé’ˆå¯¹å¤šå¤„ç†å™¨¾pÈ»Ÿä¸Šéžå¸¸å¤§(å‰å­—èŠ‚ä»¥åŠæ›´å¤§çš„)堆进行了优化ã€?

选择一¿Uç®—æ³?/STRONG>

有六¿U算法å¯ä»¥é€‰æ‹©åQŒæ?zh¨¨n)¨å¯èƒ½ä¸çŸ¥é“è¦ä½¿ç”¨å“ªä¸€¿Uã€?å›?2æä¾›äº†ä¸€äº›æŒ‡å¯û|¼Œž®†æ”¶é›†å™¨åˆ†äØ“å•线½E‹å’Œòq¶å‘的,以åŠåˆ†äؓ短暂åœå’Œé«˜åžå能力的。åªè¦æ?zh¨¨n)¨æŽŒæ¡äº†åº”用程åºå’Œéƒ¨çÖv环境的信æ¯ï¼Œž®Þpƒö以选择åˆé€‚çš„½Ž—法。对于许多应用程åºï¼Œé»˜è®¤çš„æ”¶é›†å™¨å¯ä»¥å·¥ä½œå¾—很好――因此如果æ?zh¨¨n)¨æ²¡æœ‰æ€§èƒ½é—®é¢˜åQŒé‚£ä¹ˆå°±æ²¡å¿…è¦åŠ å…¥æ›´å¤šçš„å¤æ‚性。丘q‡ï¼Œå¦‚æžœæ‚(zh¨¨n)¨çš„应用½E‹åºæ˜¯éƒ¨¾|²åœ¨å¤šå¤„ç†å™¨¾pÈ»Ÿä¸Šæˆ–者ä‹É用éžå¸¸å¤§çš„å †åQŒé‚£ä¹ˆæ”¹å˜æ”¶é›†å™¨é€‰é¡¹å¯èƒ½ä¼šæœ‰å·¨å¤§çš„æ€§èƒ½æå‡ã€?



回页�/FONT>


微调垃圾攉™›†å™?/FONT>

JDK 1.4.1 ˜q˜åŒ…括大é‡çš„微调垃圾攉™›†çš„选项。调整这些选项òq¶è¡¡é‡å®ƒä»¬çš„æ•ˆæžœå¯èƒ½ä¼šèбè´ÒŽ(gu¨©)‚¨å¤§é‡æ—‰™—´åQŒå› æ­¤åœ¨è¯•图微调垃圾攉™›†å™¨ä¹‹å‰å…ˆå¯ÒŽ(gu¨©)‚¨çš„应用程åºè¿›è¡Œå½»åº•çš„é…ç½®åQˆprofileåQ‰å’Œä¼˜åŒ–åQŒè¿™æ äh‚¨çš„微调工作å¯èƒ½ä¼šå¾—到更好的结果ã€?/P>

微调垃圾攉™›†é¦–å…ˆè¦åšçš„æ˜¯‹‚€æŸ¥å†—é•¿çš„ GC 输出。这会ä‹Éæ‚(zh¨¨n)¨å¾—到垃圾收集æ“作的频率ã€å®šæ—¶å’ŒæŒç®‹æ—‰™—´½{‰ä¿¡æ¯ã€‚最½Ž€å•的垃圾攉™›†å¾®è°ƒ?y¨­u)®±æ˜¯æ‰©å¤§æœ€å¤§å †çš„大ž®ï¼ˆ -Xmx åQ‰ã€‚éšç€å †çš„增大åQŒå¤åˆ¶æ”¶é›†ä¼šå˜å¾—更有效,所以在增大堆时åQŒæ?zh¨¨n)¨ž®±å‡ž®‘了æ¯ä¸ªå¯¹è±¡çš„æ”¶é›†æˆæœ¬ã€‚除了增加最大堆的大ž®ï¼Œ˜q˜å¯ä»¥ç”¨é€‰é¡¹ -XX:NewRatio 增加分酾l™å¹´è½ÖM»£çš„空间䆾é¢ã€‚也å¯ä»¥ç”?-Xmn 选项昑ּ指定òq´è½»ä»£çš„大å°ã€‚有兛_¾®è°ƒåžƒåœ¾æ”¶é›†çš„æ›´å¤š¾l†èŠ‚è¯·å‚é˜?å‚考资æ–?/FONT>中的几篇文章ã€?



回页�/FONT>


¾l“æŸè¯?/FONT>

éšç€ JVM çš„å‘展,默认垃圾攉™›†å™¨å˜å¾—è¶Šæ¥è¶Šå¥½äº†ã€‚JDK 1.2 åŠä»¥åŽç‰ˆæœ¬æ‰€ä½¿ç”¨çš„分代垃圾收集器æä¾›äº†æ¯”早期 JDK 所使用的标è®?清除-æ•´ç†æ”‰™›†å™¨å¥½å¾—多的分é…和攉™›†æ€§èƒ½ã€‚JDK 1.4.1 通过增加新的针对多处ç†å™¨¾pÈ»Ÿå’Œéžå¸¸å¤§çš„堆的多¾U¿ç¨‹æ”‰™›†é€‰é¡¹åQŒè¿›ä¸€æ­¥æ”¹˜q›äº†åžƒåœ¾æ”‰™›†çš„æ•ˆçއã€?/P>

下个月,我们ž®†è®¨è®ÞZ¸€äº›æœ‰å…›_žƒåœ¾æ”¶é›†çš„æ€§èƒ½¼œžè¯åQˆhints and mythsåQ‰ï¼ŒåŒ…括对象分é…çš„çœŸå®žæˆæœ¬ã€æ˜¾å¼èµ‹½Iºçš„代ä­h(hu¨¢n)和好处以åŠç»“æŸï¼ˆfinalizationåQ‰çš„代ä­h(hu¨¢n)åQŒä»¥æ­¤æ¥å®Œæˆæˆ‘们对垃圾收集的探讨ã€?/P>

回页�/FONT>


å‚考资æ–?



回页�/FONT>


关于作�/FONT>

Brian Goetz 在过åŽ?15 òq´é—´ä¸€ç›´ä»Žäº‹ä¸“业èÊYä»¶å¼€å‘。他æ˜?Quiotixçš„é¦–å¸­é¡¾é—®ï¼Œè¯¥å…¬å¸æ˜¯ä¸€å®¶ä½äºŽåŠ åˆ©ç¦ž®égºšå·žæ´›æ–¯æ‹‰å›¾æ–¯åQˆLos AltosåQ‰çš„软äšgå¼€å‘和咨询公å¸åQŒä»–也是几个 JCP 专家¾l„çš„æˆå‘˜ã€‚请å‚阅‹¹è¡Œçš„业界出版物ä¸?Brian å·²ç» å‘表和峞®†å‘表的文章。æ?zh¨¨n)¨å¯ä»¥é€šè¿‡ brian@quiotix.comä¸?Brian è”ç³»ã€?



jacky 2005-12-29 13:59 å‘表评论
]]>
优化 Java 垃圾攉™›†çš„æ€§èƒ½[转]http://www.tkk7.com/jacky/articles/25873.htmljackyjackyThu, 29 Dec 2005 05:58:00 GMThttp://www.tkk7.com/jacky/articles/25873.htmlhttp://www.tkk7.com/jacky/comments/25873.htmlhttp://www.tkk7.com/jacky/articles/25873.html#Feedback0http://www.tkk7.com/jacky/comments/commentRss/25873.htmlhttp://www.tkk7.com/jacky/services/trackbacks/25873.html

优化 Java 垃圾攉™›†çš„æ€§èƒ½

如何利用 IBM Java 虚拟机检‹¹‹å’Œè§£å†³åžƒåœ¾æ”‰™›†é—®é¢˜

developerWorks
文档选项
ž®†æ­¤™åµä½œä¸ºç”µå­é‚®ä»¶å‘é€?src="http://www.ibm.com/i/v14/icons/em.gif"

ž®†æ­¤™åµä½œä¸ºç”µå­é‚®ä»¶å‘é€?/FONT>

未显½Cºéœ€è¦?JavaScript 的文档选项


å¯ÒŽ(gu¨©)­¤™å늚„评ä­h(hu¨¢n)

帮助我们改进˜q™äº›å†…容


¾U§åˆ«: åˆçñ”

Sumit Chawla, 技术主½Ž¡ï¼ŒeServer Java Enablement, IBM

2003 òq?1 æœ?01 æ—?/P>

æ‚(zh¨¨n)¨çš„ Java 应用½E‹åºå……分利用了所˜q行çš?IBM eServer ¼‹¬äšg的能力了å—?在本文中åQŒä½œè€…将介ç»å¦‚何判断垃圾攉™›† —â€?Java 虚拟机执行的收回ä¸å†ä½¿ç”¨½Iºé—´çš„åŽåîC“QåŠ?—â€?是å¦è°ƒèŠ‚åˆ°æœ€ä½³çŠ¶æ€ã€‚ç„¶åŽï¼Œä»–å°†æä¾›ä¸€äº›è§£å†›_žƒåœ¾æ”¶é›†é—®é¢˜çš„廸™®®ã€?/BLOCKQUOTE>

½Ž€ä»?/FONT>

垃圾攉™›†å®žçްæ˜?IBM Java Virtual MachineåQˆJVMåQ‰å“­‘Šæ€§èƒ½çš„关键。其他多æ•?JVM 都需è¦å¤§é‡è°ƒæ•´æ‰èƒ½æä¾›æœ€ä¼˜æ€§èƒ½åQŒè€?IBM JVM 利用其“开½Ž±å³ç”¨â€çš„默认讄¡½®åQŒåœ¨å¤šæ•°æƒ…况下都能工作得很好。但是在æŸäº›æƒ…况下,垃圾攉™›†çš„æ€§èƒ½ä¼šèŽ«å其妙地˜q…速é™ä½Žã€‚结果å¯èƒ½å¯¼è‡´æœåŠ¡å™¨æ²¡æœ‰å“应ã€å±òq•陿­¢ä¸åŠ¨æˆ–è€…å®Œå…¨å¤±æ•ˆï¼Œòq¶å¸¸å¸æ€¼´æœ‰â€œå †½Iºé—´ä¸¥é‡ä¸èƒöâ€è¿™¾cÕd«¾pŠçš„æ¶ˆæ¯ã€‚幸˜q的是,多数情况下都很容易找到原因,通常也很å®ÒŽ(gu¨©)˜“¾U æ­£é”™è¯¯ã€?/P>

本文ž®†ä»‹¾lå¦‚ä½•ç¡®å®šé€ æˆæ€§èƒ½ä¸‹é™çš„æ½œåœ¨åŽŸå› ã€‚å› ä¸ºåžƒåœ¾æ”¶é›†æ˜¯ä¸€ä¸ªå¾ˆå¤§ã€å¾ˆå¤æ‚çš„è¯é¢˜ï¼Œæ‰€ä»¥æœ¬æ–‡æ˜¯åœ¨å·²¾lå‘表的一¾l„相å…Ïx–‡ç« çš„基础上展开讨论åQˆè¯·å‚阅å‚考资æ–?/FONT>åQ‰ã€‚è™½ç„¶æœ¬æ–‡è®¨è®ºçš„å¤šæ•°å»ø™®®éƒ½å°† Java ½E‹åºçœ‹ä½œæ˜¯ä¸€ä¸ªé»‘ç›’å­åQŒä½†ä»ç„¶æœ‰ä¸€äº›è§‚点å¯ä»¥åœ¨è®¾è®¡æˆ–ç¼–ç æ—¶˜q用åQŒä»¥é¿å…潜在的问题ã€?/P>

本文æä¾›çš„ä¿¡æ¯é€‚用于所æœ?IBM eServer òq›_°åQŒé™¤äº†å¯é‡æ–°è®„¡½®çš?JVM é…ç½®åQˆè¯·å‚阅å‚考资æ–?/FONT>åQ‰ã€‚除éžç‰¹åˆ«è¯´æ˜Žï¼Œæ–‡ä¸­çš„例å­éƒ½å–自˜q行在四处ç†å™?AIX 5.1 上的 Java 1.3.1 build ca131-20020706ã€?/P>

回页�/FONT>


å †ç®¡ç†æ¦‚˜q?/FONT>

JVM 在åˆå§‹åŒ–的过½E‹ä¸­åˆ†é…堆。堆的大ž®å–决于指定或者默认的最ž®å’Œæœ€å¤§å€ég»¥åŠå †çš„ä‹É用情å†üc€‚分é…å †å¯èƒ½å¯¹å¯è§†åŒ–堆有所帮助åQŒå¦‚å›?1 所½Cºï¼Œå…¶ä¸­æ˜„¡¤ºäº?heapbaseã€?I>heaplimit å’?heaptopã€?/P>
�1. 堆的概念视图
堆的概念视图

Heapbase 表示堆底åQŒheaptop 则表½Cºå †èƒ½å¤Ÿå¢žé•¿åˆ°çš„æœ€å¤§ç»å¯¹å€¹{€‚å·®å€û|¼ˆheaptop - heapbaseåQ‰ç”±å‘½ä×oè¡Œå‚æ•?-Xmx 军_®šã€‚è¯¥å‚æ•°å’Œå…¶ä»–å‘½ä»¤è¡Œå‚æ•°éƒ½æ˜¯åœ¨å…³äº?verbosegc å’Œå‘½ä»¤è¡Œå‚æ•°çš?developerWorks 文档中æ˜q°çš„。heaplimit 指针å¯ä»¥éšç€å †çš„æ‰©å±•上å‡åQŒéšç€å †çš„æ”¶ç¾ƒä¸‹é™ã€‚heaplimit 永远ä¸èƒ½­‘…过 heaptopåQŒä¹Ÿä¸èƒ½ä½ŽäºŽä½¿ç”¨ -Xms 指定的åˆå§‹å †å¤§å°ã€‚ä“Q何时候堆的大ž®éƒ½æ˜?heaplimit - heapbaseã€?

如果整个堆的自由½Iºé—´æ¯”例低于 -Xminf 指定的å€û|¼ˆminf 是最ž®è‡ªç”Þq©ºé—ß_¼‰åQŒå †ž®×ƒ¼šæ‰©å±•。如果整个堆的自ç”Þq©ºé—´æ¯”例高äº?-Xmaxf 指定的å€û|¼ˆmaxf 是最大自ç”Þq©ºé—ß_¼‰åQŒå †ž®×ƒ¼šæ”¶ç¾ƒã€?CODE>-Xminf å’?-Xmaxf 的默认值分别是 0.3 å’?0.6åQŒå› æ­?JVM æ€ÀL˜¯ž®è¯•ž®†å †çš„自ç”Þq©ºé—´æ¯”例维æŒåœ¨ 30% åˆ?60% ä¹‹é—´ã€‚å‚æ•?-XmineåQ?I>mine 是最ž®æ‰©å±•大ž®ï¼‰å’?-XmaxeåQ?I>maxe 是最大扩展大ž®ï¼‰æŽ§åˆ¶æ‰©å±•的增é‡ã€‚è¿™ 4 ä¸ªå‚æ•°å¯¹å›ºå®šå¤§å°çš„å †ä¸è“v作用åQˆç”¨ç›¸ç­‰çš?-Xms å’?-Xmx 值å¯åŠ?JVMåQŒè¿™æ„å‘³ç€ HeapLimit = HeapTopåQ‰ï¼Œå› äؓ固定大å°çš„å †ä¸èƒ½æ‰©å±•或收¾~©ã€?/P>

å½?Java ¾U¿ç¨‹è¯äh±‚存储æ—Óž¼Œå¦‚æžœ JVM ä¸èƒ½åˆ†é…­‘›_¤Ÿçš„å­˜å‚¨å—æ¥æ»¡­‘Œ™¿™ä¸ªè¯·æ±‚,则å¯ä»¥è¯´å‡ºçްäº?I>分é…å¤ÞpÓ|åQˆAFåQ‰ã€‚这时候就ä¸å¯é¿å…è¦è¿›è¡Œåžƒåœ¾æ”¶é›†ã€‚垃圾收集包括收集所有“ä¸å¯è¾¾çš„(unreachableåQ‰â€å¼•用,以便é‡ç”¨å®ƒä»¬æ‰€å ç”¨çš„空间。垃圾收集由è¯äh±‚分é…的线½E‹æ‰§è¡Œï¼Œæ˜¯ä¸€¿U?Stop-The-WorldåQˆSTWåQ‰æœºåˆÓž¼›æ‰§è¡Œåžƒåœ¾æ”‰™›†½Ž—法æ—Óž¼ŒJava 应用½E‹åºçš„其他所有线½E‹ï¼ˆé™¤äº†åžƒåœ¾æ”‰™›†å¸®åŠ©å™¨çº¿½E?/FONT>之外åQ‰éƒ½è¢«æŒ‚èµ—÷€?/P>

IBM 实现使用¿UîCØ“ mark-sweep-compactåQˆMSCåQ‰çš„垃圾攉™›†½Ž—法åQŒå®ƒæ˜¯æ ¹æ®ä¸‰ä¸ªä¸åŒçš„阶段命åçš„ã€?

标记
表和所有“å¯è¾„¡š„â€æˆ–者活动的对象。这个阶ŒDµä»Ž¼‹®å®šâ€œæ ¹â€å¼€å§‹ï¼Œæ¯”如¾U¿ç¨‹æ ˆä¸Šçš„对象ã€Java Native InterfaceåQˆJNIåQ‰å±€éƒ¨å¼•用和全局引用½{‰ï¼Œç„¶åŽæ²¿ç€æ¯ä¸ªå¼•用˜q›è¡Œé€’å½’åQŒç›´åˆ°æ‰€æœ‰çš„引用都åšä¸Šæ ‡è®°ã€?
清ç†
清除所有已¾l分é…但没有标记的对象,收回˜q™äº›å¯¹è±¡ä½¿ç”¨çš„空间ã€?
压羃
ž®†æ´»åŠ¨å¯¹è±¡ç§»åŠ¨åˆ°ä¸€èµøP¼ŒåŽÀLŽ‰å †ä¸­çš„ç©º‹zžï¼ˆholeåQ‰å’Œ¼„Žç‰‡ã€?

关于 MSC ½Ž—法的细节,请å‚é˜?A >å‚考资æ–?/FONT>ã€?/P>

òq¶è¡Œå’Œåƈå?/STRONG>

虽然垃圾攉™›†æœ¬èín采用 STW 机制åQŒä½†æœ€æ–°çš„ IBM JVM 版本都在多处ç†å™¨æœºå™¨ä¸Šä‹É用多个“帮助器â€çº¿½E‹ï¼Œä»¥ä¾¿å‡å°‘æ¯ä¸ªé˜¶æ®µæ‰€èŠÞp´¹çš„æ—¶é—´ã€‚因此,在默认情况下åQŒJVM 1.3.0 在标记阶ŒDµé‡‡ç”¨åƈ行模å¼ã€‚JVM 1.3.1 在标记和清ç†é˜¶æ®µéƒ½é‡‡ç”¨åƈ行模å¼ï¼Œåœ¨æ ‡è®°é˜¶ŒDµè¿˜æ”¯æŒä¸€¿Uå¯é€‰çš„òq¶å‘模å¼åQŒå¯ä»¥ä‹É用命令行开å…?-Xgcpolicy:optavgpause 切æ¢ã€‚撰写本文时åQŒæœ€æ–°ç‰ˆæœ¬çš„ JVM 1.4.0 中有一¿U递增压羃模å¼åQŒå®ƒòq¶è¡ŒåŒ–了åQˆparallelizeåQ‰åŽ‹¾~©é˜¶ŒDüc€‚è®¨è®ø™¿™äº›æ¨¡å¼æ—¶åQŒé‡è¦çš„æ˜¯è¦ç†è§£òq¶è¡Œå’Œåƈå‘的区别ã€?/P>

在拥æœ?N ä¸?CPU 的多处ç†å™¨ç³»¾lŸä¸­åQŒæ”¯æŒåƈ行模å¼çš„ JVM 在åˆå§‹åŒ–的时候会å¯åЍ N-1 个垃圾收集帮助器¾U¿ç¨‹ã€‚è¿è¡Œåº”用程åºä»£ç çš„æ—¶å€™ï¼Œ˜q™äº›¾U¿ç¨‹ä¸€ç›´å¤„于空闲状æ€ï¼Œåªæœ‰å½“å¯åŠ¨åžƒåœ¾æ”¶é›†æ—¶æ‰è°ƒç”¨å®ƒä»¬ã€‚在æŸä¸€ç‰¹å®šçš„阶ŒDµï¼Œä¼šå°†ä¸€äº›å·¥ä½œåˆ†é…给驱动垃圾攉™›†çš„线½E‹å’Œå¸®åŠ©å™¨çº¿½E‹ï¼Œå› æ­¤ä¸€å…±æœ‰ N ¾U¿ç¨‹òq¶è¡Œåœ°è¿è¡Œåœ¨ N-CPU 机器上。如果覼›æ­¢òq¶è¡Œæ¨¡å¼åQŒæƒŸä¸€çš„æ–¹æ³•是使用 -Xgcthreads 傿•°æ”¹å˜å¯åŠ¨çš„åžƒåœ¾æ”¶é›†å¸®åŠ©å™¨¾U¿ç¨‹ä¸ªæ•°ã€?/P>

采用òq¶å‘æ¨¡å¼æ—Óž¼ŒJVM 会å¯åŠ¨ä¸€ä¸ªåŽå°çº¿½E‹ï¼ˆä¸åˆ©äºŽåžƒåœ¾æ”¶é›†å¸®åЩ噍¾U¿ç¨‹åQ‰ï¼Œåœ¨æ‰§è¡Œåº”用程åºçº¿½E‹çš„åŒæ—¶åQŒéƒ¨åˆ†å·¥ä½œæ˜¯åœ¨åŽå°å®Œæˆçš„。åŽå°çº¿½E‹ä¼šè¯•ç€ä¸Žåº”用程åºåÆˆå‘æ‰§è¡Œï¼Œä»¥å®Œæˆåžƒåœ¾æ”¶é›†çš„æ‰€æœ‰æ“作,因此在执行垃圾收集时åQŒå¯ä»¥å‡ž®?STW 造æˆçš„æš‚åœã€‚但在æŸäº›æƒ…况下åQŒåƈå‘处ç†å¯èƒ½å¯¹æ€§èƒ½é€ æˆè´Ÿé¢å½±å“åQŒç‰¹åˆ«æ˜¯å¯¹äºŽ CPU æ•æ„Ÿçš„应用程åºã€?/P>

下表按照 JVM 版本列出了垃圾收集å„个阶ŒD늚„处熾cÕdž‹ã€?/P>
  标记 æ¸…ç† åŽ‹ç¾ƒ
IBM JVM 1.2.2 X X X
IBM JVM 1.3.0 P X X
IBM JVM 1.3.1 P, C P X
IBM JVM 1.4.0 P, C P P

其中åQ?

X
å•线½E‹æ“作ã€?
P
òq¶è¡Œæ“作åQˆåžƒåœ¾æ”¶é›†æœŸé—´æ‰€æœ‰å¸®åЩ噍¾U¿ç¨‹éƒ½åœ¨å·¥ä½œåQ‰ã€?
C
òq¶å‘æ“作åQˆåŽå°çº¿½E‹å’Œåº”用½E‹åº¾U¿ç¨‹òq¶å‘æ“作åQ‰ã€?



回页�/FONT>


åˆ†æž verbosegc 输出

虽然也有分枽E‹åºå’Œå…¶ä»–第三方工具åQŒä½†æœ¬æ–‡ä»…讨论对 verbosegc 日志的分æžã€‚这些日志由 JVM 在指å®?-verbosegc 命ä×oè¡Œå‚æ•°æ—¶ç”ŸæˆåQŒæ˜¯ä¸€¿Uéžå¸¸å¯é çš„独立于åã^å°çš„调试工具。è¦èŽ·å¾—å®Œæ•´çš?verbosegc 语法åQŒè¯·å‚阅â€?A target=new>verbosegc and command-line parametersâ€ã€?/P>

å¯ç”¨ verbosegc å¯èƒ½å¯¹åº”用程åºçš„æ€§èƒ½æœ‰ä¸€å®šåª„å“。如果这¿Uåª„å“æ˜¯æ— æ³•接å—的,则应该ä‹É用测试系¾lŸæ¥æ”‰™›† verbosegc 日志。æœåŠ¡å™¨åº”ç”¨½E‹åºé€šå¸¸ä¸€ç›´ä‹É verbosegc 处于‹È€‹zÈŠ¶æ€ã€‚这是监控整ä¸?JVM 是妘qè{良好的一¿U好办法åQŒåœ¨å‡ºçް OutOfMemory 错误的情况下åQŒè¿™¿U方法具有无å¯ä¼°è®¡çš„价倹{€?/P>

ä¸ÞZº†æœ‰æ•ˆåœ°åˆ†æž?verbosegc 记录åQŒå¿…™åÀLŠŠ¾_‘ÖŠ›é›†ä¸­åœ¨ç›¸å…³ä¿¡æ¯ä¸ŠåQŒåƈ˜q‡æ×o掉“噪音â€ã€‚通过¾~–写脚本从很长的 verbosegc ˜q½è¸ªè®°å½•中æå–ä¿¡æ¯åƈä¸éš¾åQŒä½†æ˜¯è¿™äº›è®°å½•的格å¼å¯èƒ½åQˆè€Œä¸”通常¼‹®å®žå¦‚æ­¤åQ‰éšä¸åŒçš?JVM 版本而异。下é¢çš„例å­ç”¨ç²—体或è“色字体表示é‡è¦çš„ä¿¡æ¯ã€‚å³ä½¿è®°å½•的格å¼çœ‹è“væ¥ç›¸å·®å¾ˆå¤§ï¼Œä¹Ÿå¾ˆå®ÒŽ(gu¨©)˜“åœ?verbosegc 日志中找到这些信æ¯ã€?/P>

æ‚(zh¨¨n)¨åˆ·æ–°çš„了å—åQ?/STRONG>

在å°è¯•本文中的å¾è®®ä¹‹å‰ï¼Œå¼ºçƒˆå»ø™®®æ‚(zh¨¨n)¨å‡¾U§åˆ°æœ€æ–°çš„ JVM æœåŠ¡åˆäh–°åQˆSRåQ‰ã€‚毋ơ进行新的æœåŠ¡åˆ·æ–°éƒ½ä¼šæœ‰å¾ˆå¤šä¿®æ­£å’Œæ”¹˜q›ï¼Œåº”用新的æœåŠ¡åˆäh–°å¯ä»¥æé«˜ JVM 的性能和稳定性。迿UÕdˆ°æœ€æ–°çš„版本åQˆæ¯”å¦?JVM 1.4.0 æˆ?1.3.1åQŒæ ¹æ®ä‹É用的òq›_°åQ‰æä¾›äº†å¢žå¼ºçš„æ€§èƒ½ç‰ÒŽ(gu¨©)€§ã€‚一定è¦ä¸?JVM 安装所有必需çš?OS è¡¥ä¸åQˆæ¯”å¦?AIX 上的¾l´æŠ¤¾U§åˆ«åQ‰ã€‚这些信æ¯è®°å½•在éš?SDK/JRE æä¾›çš?readme æ–‡äšg中ã€?/P>

正确讄¡½®å †çš„大å°

计算正确的堆大å°å‚数很容易,但它å¯èƒ½å¯¹åº”用程åºå¯åŠ¨æ—¶é—´å’Œ˜q行时性能有很大的影å“。åˆå§‹å¤§ž®å’Œæœ€å¤§å€¼åˆ†åˆ«ç”±å‚æ•° -Xms å’?-Xmx 控制åQŒè¿™äº›å€¼é€šå¸¸æ˜¯æ ¹æ®ç†æƒÏxƒ…况和é‡è´Ÿèähƒ…况下堆的使用情况的估计æ¥è®„¡½®çš„,ä½?verbosegc å¯ä»¥å¸®åŠ©¼‹®å®š˜q™äº›å€û|¼Œè€Œé¿å…胡ä¹ÞqŒœ‹¹‹ã€‚䏋颿˜¯ä»Žå¯åŠ¨åˆ°å®Œæˆ½E‹åºçš„åˆå§‹åŒ–åQˆæˆ–者进入“就¾lªâ€çжæ€ï¼‰˜q™æ®µæ—‰™—´é‡Œï¼Œä¸€ä¸ªåº”用程åºçš„ verbosegc 输出åQŒå¦‚下所½Cºã€?/P>

			
<GC[0]: Expanded System Heap by 65536 bytes
<GC[0]: Expanded System Heap by 65536 bytes

<AF[1]: Allocation Failure. need 64 bytes, 0 ms since last AF>
<AF[1]: managing allocation failure, action=1 (0/3983128) (209640/209640)>
<GC(1): GC cycle started Tue Oct 29 11:05:04 2002
<GC(1): freed 1244912 bytes, 34% free (1454552/4192768), in 10 ms>
<GC(1): mark: 9 ms, sweep: 1 ms, compact: 0 ms>
<GC(1): refs: soft 0 (age >= 32), weak 5, final 237, phantom 0>
<AF[1]: completed in 12 ms>

上述记录表明åQŒç¬¬ä¸€‹Æ¡å‘ç”?AF æ—Óž¼Œå †ä¸­çš„自ç”Þq©ºé—´äØ“ 0%åQ?983128 中有 0 字节å¯ç”¨åQ‰ã€‚此外,½W¬ä¸€‹Æ¡åžƒåœ¾æ”¶é›†ä¹‹åŽï¼Œè‡ªç”±½Iºé—´æ¯”例上å‡åˆ?34%åQŒç•¥é«˜äºŽ -Xminf 标记åQˆé»˜è®¤äØ“ 30%åQ‰ã€‚æ ¹æ®åº”用程åºçš„使用åQŒä‹Éç”?-Xms åˆ†é…æ›´å¤§çš„åˆå§‹å †å¯èƒ½ä¼šæ›´å¥½ä¸€äº›ã€‚几乎å¯ä»¥è‚¯å®šçš„æ˜¯ï¼Œä¸Šä¾‹ä¸­çš„应用½E‹åºåœ¨ä¸‹ä¸€‹Æ?AF æ—¶ä¼šå¯ÆD‡´å †æ‰©å±•ã€‚åˆ†é…æ›´å¤§çš„åˆå§‹å †å¯ä»¥é¿å…è¿™¿U情å†üc€‚一旦应用程åºè¿›å…?Ready 状æ€ï¼Œé€šå¸¸ä¸ä¼šå†é‡åˆ?AFåQŒå› æ­¤ä¹Ÿž®Þq¡®å®šäº†æ¯”较好的åˆå§‹å †å¤§ž®ã€‚类似地åQŒé€šè¿‡å¢žåŠ åº”ç”¨½E‹åºè´Ÿè²ä¹Ÿå¯ä»¥æŽ¢‹¹‹åˆ°é¿å…出现 OutOfMemory 错误çš?-Xmx 倹{€?/P>

如果堆太ž®ï¼Œå³ä‹É应用½E‹åºä¸ä¼šé•¿æœŸä½¿ç”¨å¾ˆå¤šå¯¹è±¡åQŒä¹Ÿä¼šé¢‘¾J地˜q›è¡Œåžƒåœ¾æ”‰™›†ã€‚因此,自然会出çŽîC‹É用很大的堆的們֑。但是由于åã^å°å’Œå…¶ä»–æ–šw¢çš„因素,堆的最大大ž®è¿˜å—物ç†å› ç´ çš„é™åˆ¶ã€‚如果堆被分™åµï¼Œæ€§èƒ½ž®×ƒ¼šæ€¥å‰§æ¶åŒ–åQŒå› æ­¤å †çš„大ž®ä¸€å®šä¸èƒ½è¶…出安装在¾pÈ»Ÿä¸Šçš„物ç†å†…存总é‡ã€‚比如,如果 AIX 机器上有 1 GB 的内存,ž®×ƒ¸åº”该ä¸?Java 应用½E‹åºåˆ†é… 2 GB 的堆ã€?/P>

å³ä‹É应用½E‹åºåœ¨æ‹¥æœ?64 GB 内存çš?p690 ­‘…çñ”计算æœÞZ¸Š˜q行åQŒä¹Ÿä¸ä¸€å®šå°±èƒ½ä‹Éç”?-Xmx60gåQˆå½“然是 64 ä½çš„ JVMåQ‰ã€‚虽然在很长旉™—´å†…,应用½E‹åºå¯èƒ½ä¸ä¼šé‡åˆ° AFåQŒä½†ä¸€æ—¦å‘ç”?AFåQŒSTW 造æˆçš„圙å¿å°†å¾ˆéš¾åº”付。下é¢çš„记录å–自 32 GB AIX ¾pÈ»Ÿä¸Šåˆ†é…了 20 GB 堆空间的 64 ä½?JVM 1.3.1åQˆbuild caix64131-20021102åQ‰ï¼Œå®ƒå±•½CÞZº†å¤§åž‹å †åœ¨˜q™æ–¹é¢çš„å½±å“ã€?/P>

<AF[29]: Allocation Failure. need 2321688 bytes, 88925 ms since last AF>
<AF[29]: managing allocation failure, action=1 (3235443800/20968372736) 
   (3145728/3145728)>
<GC(29): GC cycle started Mon Nov 4 14:46:20 2002
<GC(29): freed 8838057824 bytes, 57% free (12076647352/20971518464), 
   in 4749 ms>
<GC(29): mark: 4240 ms, sweep: 509 ms, compact: 0 ms>
<GC(29): refs: soft 0 (age >= 32), weak 0, final 1, phantom 0>
<AF[29]: completed in 4763 ms>

垃圾攉™›†ç”¨äº†ž®†è¿‘五秒钟,˜q˜ä¸åŒ…括压羃åQ垃圾收集周期所èŠÞp´¹çš„æ—¶é—´ç›´æŽ¥ä¸Žå †çš„大尿ˆæ­£æ¯”。一æ¡å¥½çš„原则是æ ÒŽ(gu¨©)®éœ€è¦è®¾¾|®å †çš„大ž®ï¼Œè€Œä¸æ˜¯å°†å®ƒé…¾|®å¾—太大或太ž®ã€?/P>

常è§çš„一¿U性能优化技术是ž®†åˆå§‹å †å¤§å°åQ?CODE>-XmsåQ‰è®¾æˆä¸Žæœ€å¤§å †å¤§å°åQ?CODE>-XmxåQ‰ç›¸åŒã€‚å› ä¸ÞZ¸ä¼šå‡ºçŽ°å †æ‰©å±•å’Œå †æ”¶ç¾ƒåQŒæ‰€ä»¥åœ¨æŸäº›æƒ…况下,˜q™æ ·åšå¯ä»¥æ˜¾è‘—地改善性能。通常åQŒåªæœ‰éœ€è¦å¤„ç†å¤§é‡åˆ†é…请求的应用½E‹åºæ—Óž¼Œæ‰åœ¨åˆå§‹å’Œæœ€å¤§å †å¤§å°ä¹‹é—´è®„¡½®è¾ƒå¤§çš„差倹{€‚但是è¦è®îC½åQŒå¦‚果指å®?-Xms100m -Xmx100måQŒé‚£ä¹?JVM ž®†åœ¨æ•´ä¸ªç”Ÿå‘½æœŸä¸­æ¶ˆè€?100 MB 的内存,å³ä‹É利用率中‘…过 10%ã€?/P>

å¦ä¸€æ–šw¢åQŒä¹Ÿå¯ä»¥ä½¿ç”¨ -Xinitsh 在开始的时候分é…较大的¾pÈ»Ÿå †ï¼Œä»Žè€Œé¿å…出çŽ?Expanded System Heap 消æ¯ã€‚但˜q™äº›æ¶ˆæ¯å®Œå…¨å¯ä»¥å¿½ç•¥ã€‚ç³»¾lŸå †éšç€éœ€è¦è€Œæ‰©å±•,òq¶ä¸”永远ä¸ä¼šå‘生垃圾攉™›†åQŒå®ƒåªåŒ…å«é‚£äº›åº¦˜q‡äº† JVM 实例整个生命期的对象ã€?/P>

é¿å…堆失æ•?/STRONG>

如果使用大å°å¯å˜çš„å †åQˆæ¯”如,-Xms å’?-Xmx ä¸åŒåQ‰ï¼Œåº”用½E‹åºå¯èƒ½é‡åˆ°˜q™æ ·çš„æƒ…å†µï¼Œä¸æ–­å‡ºçŽ°åˆ†é…å¤ÞpÓ|而堆没有扩展。这ž®±æ˜¯å †å¤±æ•?/I>åQŒæ˜¯ç”׃ºŽå †çš„大å°åˆšåˆšèƒ½å¤Ÿé¿å…扩展但åˆä¸èƒö以解决以åŽçš„分é…å¤ÞpÓ|而造æˆçš„。通常åQŒåžƒåœ¾æ”¶é›†å‘¨æœŸé‡Šæ”„¡š„½Iºé—´ä¸ä»…å¯ä»¥æ»¡èƒö当å‰çš„分é…失败,而且˜q˜æœ‰å¾ˆå¤šå¯ä¾›ä»¥åŽçš„分é…请求ä‹É用的½Iºé—´ã€‚但是,如果堆处于失效状æ€ï¼Œé‚£ä¹ˆæ¯ä¸ªåžƒåœ¾æ”‰™›†å‘¨æœŸé‡Šæ”¾çš„空间刚刚能够满­‘›_½“å‰çš„分é…å¤ÞpÓ|。结果,下一‹Æ¡åˆ†é…请求时åQŒåˆä¼šè¿›å…¥åžƒåœ¾æ”¶é›†å‘¨æœŸï¼Œä¾æ­¤¾cÀLŽ¨ã€‚å¤§é‡ç”Ÿå­˜æ—¶é—´å¾ˆçŸ­çš„对象也å¯èƒ½é€ æˆ˜q™ç§çŽ°è±¡ã€?/P>

é¿å…˜q™ç§å¾ªçŽ¯çš„ä¸€¿U办法是增加 -Xminf å’?-Xmaxf 的倹{€‚比方说åQŒå¦‚æžœä‹Éç”?-Xminf.5åQŒå †ž®†å¢žé•¿åˆ°è‡›_°‘æœ?50% 的自ç”Þq©ºé—´ã€‚åŒæ øP¼Œå¢žåŠ  -Xmaxf 也是很åˆç†ã€‚如æž?-Xminf.5 ½{‰äºŽ 5åQ?CODE>-Xmaxf 为默认å€?0.6åQŒå› ä¸?JVM è¦æŠŠè‡ªç”±½Iºé—´æ¯”ä¾‹ä¿æŒåœ?50% å’?60% 之间åQŒæ‰€ä»¥å°±ä¼šå‡ºçŽ°å¤ªå¤šçš„æ‰©å±•å’Œæ”¶¾~©ã€‚两者相å·?0.3 是一个ä¸é”™çš„选择åQŒè¿™æ ?-Xmaxf.8 å¯ä»¥å¾ˆå¥½åœ°åŒ¹é…?-Xminf.5ã€?/P>

如果记录表明åQŒéœ€è¦å¤š‹Æ¡æ‰©å±•æ‰èƒ½è¾¾åˆ°ç¨³å®šçš„堆大ž®ï¼Œä½†å¯ä»¥æ›´æ”?-XmineåQŒæ ¹æ®åº”用程åºçš„è¡ŒäØ“æ¥è®¾¾|®æ‰©å±•大ž®çš„æœ€ž®å€¹{€‚目标是获得­‘›_¤Ÿçš„å¯ç”¨ç©ºé—ß_¼Œä¸ä»…能满­‘›_½“å‰çš„è¯äh±‚åQŒè€Œä¸”能满­‘³ä»¥åŽçš„很多è¯äh±‚åQŒä»Žè€Œé¿å…过多的垃圾攉™›†å‘¨æœŸã€?CODE>-Xmineã€?CODE>-Xmaxf å’?-Xminf 为控制应用程åºçš„内存使用ç‰ÒŽ(gu¨©)€§æä¾›äº†å¾ˆå¤§çš„絋zÀL€§ã€?/P>

标记栈溢�/STRONG>

使用 verbosegc 最é‡è¦çš„一™åÒŽ(gu¨©)£€æŸ¥æ˜¯æ²¡æœ‰å‡ºçŽ°â€œmark stack overflowâ€æ¶ˆæ¯ã€‚下é¢çš„记录昄¡¤ºäº†è¿™¿U消æ¯åŠå…¶åª„å“ã€?/P>

<AF[50]: Allocation Failure. need 272 bytes, 18097 ms since last AF>
<AF[50]: managing allocation failure, action=1 (0/190698952) 
   (9584432/10036784)>
<GC(111): mark stack overflow>
<GC(111): freed 77795928 bytes in 1041 ms, 43% free (87380360/200735736)>
<GC(111): mark: 949 ms, sweep: 92 ms, compact: 0 ms>
<GC(111): refs: soft 0 (age >= 32), weak 0, final 0, phantom 0>
<AF[50]: completed in 1042 ms>

在垃圾收集的标记阶段åQŒå¦‚æžœå¼•ç”¨çš„ä¸ªæ•°é€ æˆ JVM å†…éƒ¨çš„â€œæ ‡è®°æ ˆâ€æº¢å‡ºï¼Œž®×ƒ¼šå¼•员q™ç§æ¶ˆæ¯ã€‚在标记阶段åQŒåžƒåœ¾æ”¶é›†å¤„ç†ä»£ç ä‹É用这个栈压入所有已知的引用åQŒä»¥ä¾‰K€’å½’æ‰«ææ¯ä¸ª‹zÕdŠ¨å¼•ç”¨ã€‚æº¢å‡ºçš„åŽŸå› æ˜¯å †ä¸­çš„‹zÕdŠ¨å¯¹è±¡˜q‡å¤šåQˆæˆ–者更准确地说åQŒå¯¹è±¡åµŒå¥—过深)åQŒè¿™é€šå¸¸è¡¨æ˜Žåº”用½E‹åºä»£ç å­˜åœ¨¾~ºé™·ã€‚除éžèƒ½å¤Ÿé€šè¿‡å¤–部讄¡½®æŽ§åˆ¶åº”用½E‹åºä¸­çš„‹zÕdŠ¨å¯¹è±¡ä¸ªæ•°åQˆæ¯”如柿U对象池åQ‰ï¼Œé‚£ä¹ˆéœ€è¦åœ¨åº”用½E‹åºæºä»£ç ä¸­è§£å†³˜q™ä¸ªé—®é¢˜ã€‚å¾è®®ä‹É用分æžå·¥å…ïL¡®å®šæ´»åŠ¨çš„å¼•ç”¨ã€?/P>

如果ä¸èƒ½é¿å…大é‡çš„æ´»åŠ¨å¼•ç”¨ï¼Œòq¶å‘标记å¯èƒ½æ˜¯ä¸€¿Uå¯è¡Œçš„选择ã€?/P>

摆脱 finalizer

下é¢çš„记录显½CÞZº†ä¸€¿U有­‘£çš„æƒ…况åQšè§£å†›_ˆ†é…失败花费了 2.78 ¿U’é’ŸåQŒå…¶ä¸­è¿˜ä¸åŒ…括压¾~©æ‰€ç”¨çš„æ—‰™—´ã€?/P>

<AF[1]: Allocation Failure. need 56 bytes, 0 ms since last AF>
<AF[1]: managing allocation failure, action=1 (0/521140736) 
   (3145728/3145728)>
<GC(1): GC cycle started Thu Aug 29 19:25:45 2002
<GC(1): freed 321890808 bytes, 61% free (325036536/524286464), in 2776 ms>
<GC(1): mark: 2672 ms, sweep: 104 ms, compact: 0 ms>
<GC(1): refs: soft 0 (age >= 32), weak 11, final 549708, phantom 0>
<AF[1]: completed in 2780 ms>

¾|ªé­¼œ”R¦–是必™å»è¢«¾l“æŸæŽ‰çš„å¯¹è±¡æ•°é‡ã€‚无论如何,使用 finalizer 䏿˜¯ä¸€ä¸ªå¥½ä¸ÀL„åQŒè™½ç„¶åœ¨ç‰¹å®šçš„æƒ…况下˜q™æ˜¯ä¸å¯é¿å…的,但是应该仅仅ž®†å®ƒä½œäؓ完æˆå…¶ä»–æ–ÒŽ(gu¨©)³•ä¸èƒ½å®žçŽ°çš„æ“作的ä¸å¾—已方法。比方说åQŒæ— è®ºå¦‚何都è¦é¿å…在 finalizer 内部执行分é…ã€?/P>

é¿å…éžå¸¸å¤§çš„分é…

æœ‰æ—¶å€™é—®é¢˜ä¸æ˜¯ç”±å½“时的堆状æ€é€ æˆçš„ï¼Œè€Œæ˜¯å› äØ“åˆ†é…å¤ÞpÓ|造æˆçš„。比如:


<AF[212]: Allocation Failure. need 912920 bytes, 34284 ms since last AF>
<AF[212]: managing allocation failure, action=2 (117758504/261028856)>
<GC(273): freed 65646648 bytes in 2100 ms, 70% free (183405152/261028856)>
<GC(273): mark: 425 ms, sweep: 89 ms, compact: 1586 ms>
<GC(273): refs: soft 0 (age >= 32), weak 0, final 0, phantom 0>
<GC(273): moved 755766 objects, 43253888 bytes, reason=0, used x4C0 more 
   bytes>
<AF[212]: completed in 2101 ms>

˜q™äº›è®°å½•æ¥è‡ªä¸€ä¸ªéžå¸¸è€çš„ JVMåQˆå‡†¼‹®åœ°è¯´æ˜¯ ca130-20010615åQ‰ï¼Œå› æ­¤åŽ‹ç¾ƒçš„åŽŸå› ï¼ˆ¾U¢è‰²æ˜„¡¤ºåQ‰æ˜¾½CÞZØ“ 0。但是压¾~?256 MB 的堆èŠÞp´¹äº?1.5 ¿U’ï¼ä¸ÞZ½•˜q™ä¹ˆå·®ï¼Ÿå†æ¥çœ‹ä¸€çœ‹æœ€åˆçš„è¯äh±‚åQŒæœ€åˆè¯·æ±‚çš„æ˜?912920 字节 —â€?ž®†è¿‘ 1 MBã€?/P>

分é…的内存å—都必™åÀL˜¯˜qžç®‹çš„,而éšç€å †è¶Šæ¥è¶Šæ»¡ï¼Œæ‰‘Öˆ°è¾ƒå¤§çš„连¾l­å—­‘Šæ¥­‘Šå›°éš¾ã€‚è¿™ä¸ä»…仅是 Java 的问题,使用 C 中的 malloc 也会é‡åˆ°˜q™ä¸ªé—®é¢˜ã€‚JVM 在压¾~©é˜¶ŒDµé€šè¿‡é‡æ–°åˆ†é…引用æ¥å‡ž®‘碎片,但其代ä­h(hu¨¢n)是è¦å†È»“应用½E‹åºè¾ƒé•¿çš„æ—¶é—´ã€‚上é¢çš„记录表明已ç»å®Œæˆäº†åŽ‹¾~©é˜¶ŒDµï¼Œåˆ†é…一大嗽Iºé—´çš„æ€ÀL—¶é—´è¶…˜q‡äº† 2¿U’ã€?/P>

下é¢çš„记录说明了最¾pŸç³•的一¿U情å†üc€?/P>

<AF[370]: Allocation Failure. need 2241056 bytes, 613 ms since last AF>
<AF[370]: managing allocation failure, action=2 (135487112/1291844600)>
<GC: Wed Oct 16 10:16:46 2002
<GC(455): freed 41815176 bytes in 28663 ms, 13% free (177302288/1291844600)>
<GC(455): mark: 3233 ms, sweep: 328 ms, compact: 25102 ms>
<GC(455): refs: soft 0 (age >= 32), weak 0, final 17, phantom 0>
<GC(455): moved 15822115 objects, 615093008 bytes, reason=1, used x698 
   more bytes>
<AF[370]: managing allocation failure, action=3 (177302288/1291844600)>
<AF[370]: managing allocation failure, action=4 (177302288/1291844600)>
<AF[370]: clearing all remaining soft refs>
<GC(456): freed 176216 bytes in 3532 ms, 13% free (177478504/1291844600)>
<GC(456): mark: 3215 ms, sweep: 317 ms, compact: 0 ms>
<GC(456): refs: soft 16 (age >= 32), weak 0, final 0, phantom 0>
<GC(457): freed 9592 bytes in 23781 ms, 13% free (177488096/1291844600)>
<GC(457): mark: 3231 ms, sweep: 315 ms, compact: 20235 ms>
<GC(457): refs: soft 0 (age >= 32), weak 0, final 0, phantom 0>
<GC(457): moved 2794668 objects, 110333360 bytes, reason=1, used x30 more 
   bytes>
<AF[370]: managing allocation failure, action=5 (177488096/1291844600)>
<AF[370]: totally out of heap space>
<AF[370]: completed in 268307 ms>

è¯äh±‚的是一ä¸?2 MB 的对象(2241056 bytesåQ‰ï¼Œè™½ç„¶åœ?1.2 GB 的堆åQ?291844600åQ‰ä¸­æœ?135 MB (135487112) 自由½Iºé—´åQŒä½†å´ä¸èƒ½åˆ†é…一ä¸?2 MB çš„å—。虽然进行了一切å¯èƒ½çš„æœçƒ¦åQŒèŠ±è´¹äº† 268 ¿U’,但ä»ç„¶æ²¡æœ‰æ‰¾åˆ°èƒö够大的å—。而且˜q˜å‡ºçŽîCº†¾pŸç³•的“堆½Iºé—´ä¸¥é‡ä¸èƒöâ€æ¶ˆæ¯ï¼ŒæŒ‡å‡º JVM 的内存中‘Ÿë€?/P>

最好的办法是:如果å¯èƒ½çš„è¯åQŒæŠŠåˆ†é…è¯äh±‚分解æˆè¾ƒ?y¨­u)®çš„å—ã€‚è¿™æ øP¼Œè¾ƒå¤§çš„å †½Iºé—´å¯èƒ½ä¼šè“v作用åQŒä½†å¤šæ•°æƒ…况下,˜q™æ ·åšåªæ˜¯æŽ¨˜qŸäº†é—®é¢˜å‡ºçŽ°çš„æ—¶é—´ã€?/P>

¼„Žç‰‡åŠå…¶æˆå› 

我们å†çœ‹ä¸€çœ‹ä¸Šä¾‹ä¸­çš„其中一行:


<GC(455): freed 41815176 bytes in 28663 ms, 13% free 
   (177302288/1291844600)>

虽然æœ?177 MB 的自ç”Þq©ºé—ß_¼Œå´ä¸èƒ½åˆ†é…?2 MB çš„å—。原因在于:虽然垃圾攉™›†å‘¨æœŸå¯ä»¥åŽ‹ç¾ƒå †ä¸­çš„å­”‹zžï¼Œä½†æ˜¯å †ä¸­æœ‰äº›å†…容ä¸èƒ½åœ¨åŽ‹¾~©è¿‡½E‹ä¸­é‡æ–°åˆ†é…。比如,应用½E‹åºå¯èƒ½ä½¿ç”¨ JNI 分é…和引用对象或数组。这些分é…在内存中是固定的,既ä¸èƒ½è¢«é‡æ–°åˆ†é…åQŒä¹Ÿä¸èƒ½è¢«å›žæ”Óž¼Œé™¤éžä½¿ç”¨é€‚当çš?JNI 调用æ¥é‡Šæ”‘Ö®ƒä»¬ã€‚IBM Java æœåŠ¡å›¢é˜Ÿå¯ä»¥å¸®åŠ©¼‹®å®š˜q™ç±»å¼•用åQŒåœ¨˜q™ç§æƒ…况下,分æžå·¥å…·ä¹Ÿå¤§æœ‰ç”¨æ­¦ä¹‹åœ°ã€?/P>

¾cÖM¼¼åœŽÍ¼Œå› äØ“¾cÕd—是在堆的外部引用的,因此也是固定的。å³ä½¿æ²¡æœ‰å›ºå®šçš„对象åQŒå¤§çš„分é…一般也会导致出现碎片。所òq¸çš„æ˜¯ï¼Œ˜q™ç±»ä¸¥é‡çš„碎片很ž®‘出现ã€?/P>

需è¦åÆˆå‘æ ‡è®°å—åQ?/STRONG>

如果ç”׃ºŽåžƒåœ¾æ”‰™›†é€ æˆ Java 应用½E‹åºä¸æ—¶åœ°åœ™å¿ï¼Œòq¶å‘标记å¯ä»¥å¸®åŠ©å‡å°‘åœé¡¿çš„æ—¶é—ß_¼Œä½¿åº”用程åºè¿è¡Œæ›´òq³ç¨³ã€‚但有时候,òq¶å‘标记å¯èƒ½ä¼šé™ä½Žåº”用程åºçš„åžå能力。å¾è®®åˆ†åˆ«ä‹É用和¼›æ­¢òq¶å‘标记åQŒä‹É用相åŒçš„è´Ÿè·æ¥æµ‹é‡å¯¹åº”用½E‹åºæ€§èƒ½çš„媄å“,òq¶åŠ ä»¥æ¯”è¾ƒã€?/P>

但是åQŒè§‚å¯ŸåÆˆå‘æ ‡è®°è¿è¡Œçš„ verbosegc 输出å¯èƒ½æä¾›å¤§é‡å…³äºŽåŠ é€Ÿçš„ä¿¡æ¯ã€‚ä¸éœ€è¦åˆ†æžæ‰“å°å‡ºæ¥çš„记录的æ¯ä¸€éƒ¨åˆ†åQŒæœ‰æ„ä¹‰çš„éƒ¨åˆ†åŒ…æ‹¬åÆˆå‘æ ‡è®°èƒ½å¤ŸæˆåŠŸæ‰«æçš„æ¦‚率åQˆEXHAUSTED å’?ABORTED/HALTEDåQ‰ï¼Œä»¥åŠåŽå°¾U¿ç¨‹èƒ½å¤Ÿåšå¤šž®‘工作ã€?/P>

下é¢çš„三个记录属于åŒä¸€ä¸?Java 应用½E‹åºåQŒæ˜¯åœ¨ä¸€‹Æ¡è¿è¡Œä¸­çš„ä¸åŒé˜¶ŒDµåˆ›å»ºçš„åQŒå®ƒä»¬è¯´æ˜Žäº†òq¶å‘˜q行的三¿Uä¸åŒç»“æžœã€?/P>

½W¬ä¸€¿Uå¯èƒ½çš„¾l“æžœæ˜¯åÆˆå‘æ ‡è®°å¾—åˆ?EXHAUSTEDåQ?/P>

<CON[3]: Concurrent collection, (3457752/533723648) (3145728/3145728), 
   23273 ms since last CON>
<GC(246): Concurrent EXHAUSTED by Background helper . Target=82856559 
   Traced=57287216 (3324474+53962742) Free=3457752>
<GC(246): Cards cleaning Done. cleaned:13668 (33 skipped). Initial count 
   13701 (Factor 0.142)>
<GC(246): GC cycle started Tue Oct 1 00:05:56 2002
<GC(246): freed 436622248 bytes, 82% free (443225728/536869376), in 218 ms>
<GC(246): mark: 51 ms, sweep: 167 ms, compact: 0 ms>
<GC(246): In mark: Final dirty Cards scan: 43 ms 158 cards (total:127 ms)
<GC(246): refs: soft 0 (age >= 32), weak 0, final 5, phantom 0>
<CON[3]: completed in 230 ms>

˜q™è¡¨æ˜ŽåÆˆå‘æ ‡è®°æŒ‰ç…§æˆ‘们所预期的那样工作。EXHAUSTED æ„味ç€åŽå°¾U¿ç¨‹èƒ½å¤Ÿåœ¨å‡ºçŽ°åˆ†é…失败之å‰å®Œæˆè‡ªå·Þqš„工作。因为åŽå°çº¿½E‹æ‰«æäº† 3324474 个字节(而应用程åºçº¿½E‹æ‰«æäº† 53962742 个字节)åQŒåŽå°çº¿½E‹èƒ½å¤ŸèŽ·å¾—èƒö够的 CPU æ—‰™—´æ¥å‡ž®‘æ€Èš„æ ‡è®°æ—‰™—´ã€‚因此,STW 中的标记阶段åªç”¨äº?51 毫秒åQˆmsåQ‰ï¼Œæ€Èš„ STW æ—‰™—´ä¹Ÿä¸˜q?230 毫秒。这对于 512 MB 的堆æ¥è¯´åQŒè¿™å·²ç»å¾ˆä¸é”™äº†ã€?/P>

䏋颿˜?ABORTED òq¶å‘标记˜q行åQ?/P>

<AF[164]: Allocation Failure. need 962336 bytes, 75323 ms since last AF>
<AF[164]: managing allocation failure, action=1 (83408328/533723648) 
   (3145728/3145728)>
<GC(247): Concurrent ABORTED. Target=84703195 Traced=0 (0+0) Free=83408328>
<GC(247): GC cycle started Tue Oct 1 00:06:22 2002
<GC(247): freed 350077400 bytes, 81% free (436631456/536869376), in 896 ms>
<GC(247): mark: 695 ms, sweep: 201 ms, compact: 0 ms>
<GC(247): refs: soft 0 (age >= 32), weak 0, final 7, phantom 0>
<AF[164]: completed in 912 ms>
<CONCURRENT GC Free= 11530600 Expected free space= 11526488 Kickoff=11530370>
< Initial Trace rate is 8.00>

˜q™æ˜¯æœ€¾pŸç³•的情å†üc€‚åÆˆå‘æ ‡è®°è¢«¾lˆæ­¢åQŒä¸»è¦æ˜¯å› äØ“è¦åˆ†é…大型对象和调用äº?System.gc()。如果应用程åºé¢‘¾J地˜q™æ ·åšï¼Œé‚£ä¹ˆž®×ƒ¸èƒ½ä»Žòq¶å‘标记中获得好处ã€?/P>

最好是 HALTED òq¶å‘标记åQ?/P>

<AF[168]: Allocation Failure. need 139280 bytes, 25520 ms since last AF>
<AF[168]: managing allocation failure, action=1 (11204296/533723648) 
   (3145728/3145728)>
<GC(251): Concurrent HALTED (state=64). Target=118320773 Traced=35469830 
   (14765196+20704634) Free=11204296>
<GC(251): No Dirty Cards cleaned (Factor 0.177)>
<GC(251): GC cycle started Tue Oct 1 00:08:06 2002
<GC(251): freed 385174400 bytes, 74% free (399524424/536869376), in 389 ms>
<GC(251): mark: 274 ms, sweep: 115 ms, compact: 0 ms>
<GC(251): In mark: Final dirty Cards scan: 46 ms 2619 cards (total:225 ms)
<GC(251): refs: soft 0 (age >= 32), weak 0, final 6, phantom 0>
<AF[168]: completed in 414 ms>

ä»ŽåÆˆå‘æ ‡è®°çš„应用æ¥çœ‹åQŒHALTED 介于 EXHAUSTED å’?ABORTED 之间åQŒå®ƒè¡¨æ˜Žåªå®Œæˆäº†éƒ¨åˆ†å·¥ä½œã€‚上é¢çš„记录说明åQŒåœ¨˜q›è¡Œä¸‹ä¸€‹Æ¡åˆ†é…失败之å‰ï¼Œæ²¡æœ‰å®Œæˆæ‰«æã€‚在垃圾攉™›†å‘¨æœŸä¸­ï¼Œæ ‡è®°é˜¶æ®µèŠÞp´¹äº?274 毫秒åQŒæ€Èš„æ—‰™—´ä¸Šå‡åˆ?414 毫秒ã€?/P>

åœ¨ç†æƒ³çš„æƒ…况下,多数垃圾攉™›†å‘¨æœŸéƒ½åÆˆå‘æ”¶é›†ï¼ˆç”׃ºŽòq¶å‘标记完æˆå…¶å·¥ä½œè€Œè§¦å‘,标记ä¸?EXHAUSTEDåQ‰ï¼Œè€Œä¸æ˜¯å‡ºçŽ°åˆ†é…失败。如果应用程åºè°ƒç”?System.gc()åQŒè®°å½•中会出现很å¤?ABORTED 行ã€?/P>

在多数应用程åºä¸­åQŒåÆˆå‘æ ‡è®°éƒ½å¯ä»¥æ”¹å–„性能åQŒå¯¹äºŽâ€œæ ‡è®°æ ˆæº¢å‡ºâ€ä¹Ÿæœ‰æ‰€å¸®åŠ©ã€‚ä½†æ˜¯ï¼Œå¦‚æžœæ ‡è®°æ ˆæº¢å‡ºæ˜¯ç”׃ºŽ¾~ºé™·é€ æˆçš„,惟一的解军_Šžæ³•å°±æ˜¯ä¿®æ­£ç¼ºé™—÷€?/P>

应该é¿å…的开å…?/STRONG>

下列命ä×o行开兛_º”é¿å… 使用ã€?/P>
命ä×o行开å…?/B> 说明
-Xnocompactgc è¯¥å‚æ•°å®Œå…¨å…³é—­åŽ‹¾~©ã€‚虽然在性能斚w¢æœ‰çŸ­æœŸçš„好处åQŒæœ€¾lˆåº”用程åºå †ž®†å˜å¾—支¼›È ´¼„Žï¼Œå³ä‹É堆中有èƒö够的自由½Iºé—´ä¹Ÿä¼šå¯ÆD‡´ OutOfMemory 错误
-Xcompactgc ä½¿ç”¨è¯¥å‚æ•°å°†å¯ÆD‡´æ¯ä¸ªåžƒåœ¾æ”‰™›†å‘¨æœŸéƒ½æ‰§è¡ŒåŽ‹¾~©ï¼Œæ— è®ºæ˜¯å¦æœ‰å¿…è¦ã€‚JVM 在压¾~©æ—¶è¦åšå¤§é‡çš„决½{–,在普通模å¼ä¸‹ä¼šæŽ¨˜qŸåŽ‹¾~?/TD>
-Xgcthreads è¯¥å‚æ•°æŽ§åˆ?JVM 在å¯åŠ¨è¿‡½E‹ä¸­åˆ›å¾çš„垃圾收集帮助器¾U¿ç¨‹ä¸ªæ•°ã€‚对äº?N-处ç†å™¨æœºå™¨ï¼Œé»˜è®¤çš„线½E‹æ•°ä¸?N-1。这些线½E‹æä¾›åƈ行标记和òq¶è¡Œæ¸…ç†æ¨¡å¼ä¸­çš„òq¶è¡Œæœºåˆ¶


回页�/FONT>


¾l“æŸè¯?/FONT>

本文½Ž€å•介¾l了 IBM JVM 的垃圾收集和堆管ç†èƒ½åŠ›ã€‚ä»¥åŽçš„ verbosegc 日志很å¯èƒ½æä¾›æ›´å¤šæœ‰ç”¨çš„ä¿¡æ¯ã€?/P>

æ€È»“一下文中æå‡ºçš„廸™®®åQ?/P>

  • åªè¦å¯èƒ½ž®±å‡¾U§åˆ°æœ€æ–°çš„ JVM 版本。æ?zh¨¨n)¨é‡åˆ°çš„错误å¯èƒ½å·²¾l被å‘现òq¶è§£å†³äº†ã€?
  • 调整 -Xmsã€?CODE>-Xmx å’?-XminfåQŒç›´åˆ?verbosegc 输出¾l™å‡ºåˆ†é…å¤ÞpÓ|æ•°é‡ä¸Žæ¯‹Æ¡åžƒåœ¾æ”¶é›†é€ æˆçš„åœ™å¿æ•°é‡ä¹‹é—´çš„ä¸€ä¸ªå¯æŽ¥å—òqŒ™¡¡ã€‚ä‹É用固定大ž®çš„å †é¿å…æ”¶¾~©æˆ–扩展ã€?
  • 如果å¯èƒ½çš„è¯åQŒå°†è¾ƒå¤§çš„(>500 KBåQ‰å—åˆ†è§£æˆæ›´ž®çš„å—ã€?
  • ä¸è¦å¿½ç•¥â€œæ ‡è®°æ ˆæº¢å‡ºâ€æ¶ˆæ¯ã€?
  • é¿å…使用 finalizerã€?
  • è¯•ä¸€è¯•åÆˆå‘æ ‡è®°ã€?
  • é—®é—®æ˜¯å¦æœ‰å¿…è¦è°ƒç”?System.gc()åQŒå¦‚果没有必è¦åˆ™åˆ é™¤å®ƒã€?

如æ?zh¨¨n)¨æ‰€è§ï¼Œ˜q™ä¸ªè¯é¢˜å¯ä¸æ˜¯ä¸‰­a€ä¸¤è¯­ž®Þpƒ½è¯´æ˜Žç™½çš„。但是,åªéœ€è¦æ‰“ä¸€ä¸ªç”µè¯æˆ–者å‘一ž®ç”µå­é‚®ä»Óž¼Œž®Þpƒ½ä¸Žæ?zh¨¨n)¨çš„好伙ä¼?IBM Technical Support Team å–å¾—è”ç³»åQ?A >å‚考资æ–?/FONT>中的链接是很好的èµïL‚¹åQ‰ã€‚对于æ?zh¨¨n)¨é‡åˆ°çš„特ŒDŠæƒ…å†µï¼Œä»–ä»¬è¦æ¯”ä»ÖM½•文章都更清楚ã€?/P>

回页�/FONT>


å‚考资æ–?

  • æ‚(zh¨¨n)¨å¯ä»¥å‚阅本文在 developerWorks å…¨çƒç«™ç‚¹ä¸Šçš„ 英文原文ã€?BR>
  • Sam Borman 关于 IBM JVM Storage ¾l„äšg的系列文章是 IBM Java 垃圾攉™›†å®žçŽ°çš„æœ€è¯¦å°½çš„å‚考资料:
    • â€?A >Sensible sanitation: Understanding the IBM Java Garbage Collector, Part 1: Object Allocationâ€ï¼ˆdeveloperWorksåQ?002 òq?8 月)
    • â€?A >Sensible sanitation: Understanding the IBM Java Garbage Collector, Part 2: Garbage Collectionâ€ï¼ˆdeveloperWorksåQ?002 òq?8 月)
    • â€?A >Sensible sanitation: Understanding the IBM Java Garbage Collector, Part 3: verbosegc and command-line parametersâ€ï¼ˆdeveloperWorksåQ?002 òq?9 月)

  • 误‚®¿é—?Java 2 on the OS/390 and z/OS Platforms 站点åQŒå…³äºŽå¯é‡ç½® JVM 的信æ¯ï¼Œè¯·å‚é˜?New IBM Technology featuring Persistent Reusable Java Virtual Machines (PDF)ã€?BR>
  • artima.com çš?Inside Java 2 Virtual Machine 中,â€?A >Heap of Fishâ€å¯¹ Mark-Sweep-Compact ½Ž—法作了很好的介¾lã€?BR>
  • 如果需è¦å¸®åŠ©çš„è¯ï¼Œè¯¯‚®¿é—?IBM eServer 技术支æŒ?/FONT>™åµé¢ã€?BR>
  • 关于 IBM æœåŠ¡å™¨çš„åº”ç”¨æ–šw¢åQŒå¯ä»¥åœ¨ IBM eServer Developer Domain 上å¯ä»¥æ‰¾åˆ°æ›´å¤šæŠ€æœ¯æ–‡ç« ã€?BR>
  • developerWorks Java 技术专åŒ?/FONT>有数癄¡¯‡çš„æŠ€æœ¯æ–‡ç« å’Œæ•™ç¨‹ã€?BR>


回页�/FONT>


关于作�/FONT>

author

Sumit Chawla åœ?IBM eServer 部门ä¸?ISV æä¾› Java 支æŒã€‚æ?zh¨¨n)¨å¯ä»¥é€šè¿‡ sumitc@us.ibm.com 和他è”ç³»ã€?/P>



jacky 2005-12-29 13:58 å‘表评论
]]>
å…Ïx³¨æ€§èƒ½: 调优垃圾攉™›†[转]http://www.tkk7.com/jacky/articles/25872.htmljackyjackyThu, 29 Dec 2005 05:56:00 GMThttp://www.tkk7.com/jacky/articles/25872.htmlhttp://www.tkk7.com/jacky/comments/25872.htmlhttp://www.tkk7.com/jacky/articles/25872.html#Feedback0http://www.tkk7.com/jacky/comments/commentRss/25872.htmlhttp://www.tkk7.com/jacky/services/trackbacks/25872.html

å…Ïx³¨æ€§èƒ½: 调优垃圾攉™›†

ž®?100 MB çš„åžƒåœ¾æ‰“åŒ…æˆ 50 MB 的包

developerWorks
文档选项
ž®†æ­¤™åµä½œä¸ºç”µå­é‚®ä»¶å‘é€?src="http://www.ibm.com/i/v14/icons/em.gif"

ž®†æ­¤™åµä½œä¸ºç”µå­é‚®ä»¶å‘é€?/FONT>

未显½Cºéœ€è¦?JavaScript 的文档选项


å¯ÒŽ(gu¨©)­¤™å늚„评ä­h(hu¨¢n)

帮助我们改进˜q™äº›å†…容


¾U§åˆ«: åˆçñ”

Jack Shirazi, 董事, JavaPerformanceTuning.com
Kirk Pepperdine, CTO, JavaPerformanceTuning.com

2004 òq?7 æœ?30 æ—?/P>

如果æ‚(zh¨¨n)¨æ˜¯å½“å‰å†™ç½‘志(bloggingåQ‰ç‹‚热者中的一员,则å¯èƒ½å¬è¯´è¿‡ Blog-CityåQŒè¿™æ˜¯ç”±è‹æ ¼å…°çš„一家å°å…¬å¸ Blog-City Ltd. 拥有和è¿è¥çš„¾|‘å¿—ç«™ç‚¹ã€‚å½“ä¸€äº›æ„æ–™ä¹‹å¤–的性能问题½H然出现æ—Óž¼ŒJava 性能专家 Jack Shirazi å’?Kirk Pepperdine 被邀请帮助进è¡?Blog-City 的技术调整。他们的‹‚€‹¹‹å·¥ä½œå› ä¸ºå—¼‹¬äšg¾U¦æŸå’Œæ•´ä¸ªé¡¹ç›®æ‰€ä½¿ç”¨çš„通信通é“åQˆIRCã€ftp å’?å¶å°”的电å­é‚®ä»Óž¼‰çš„é™åˆ¶è€Œå˜å¾—夿‚ã€?/BLOCKQUOTE>

éšç€¾|‘å¿—ä½œäØ“å…¬å…±æ—¥è®°çš„æµè¡Œï¼Œ¾|‘å¿—ä¸ÀLœº˜q…速地增长。所以对äº?Blog-City çš„ähæ¥è¯´åQŒéžå¸¸æ¸…楚他们的站点需è¦å‘展和æé«˜ã€‚äØ“äº†æ»¡­‘›_…¶å¢žé•¿çš„需è¦ï¼Œè¯¥å…¬å¸æœ€˜q‘刚刚推å‡ÞZº† Blog-City version 2.0。正åƒç»å¸¸å‡ºçŽ°çš„æƒ…å†µé‚£æ ·åQŒå½“新的应用½E‹åºè½¬å…¥˜q行阶段æ—Óž¼Œç”׃ºŽå„ç§åŽŸå› åQŒå…¶æ€§èƒ½æ— æ³•完全满èƒöæœŸæœ›çš„è¦æ±‚,½Hç„¶å‡ºçŽ°éšæœºçš„é•¿æ—‰™—´åº”用½E‹åºè¢«æŒ‚èµïLš„现象˜q˜ä¸æ˜¯æœ€å的情况ã€?/P>

在其核心åQŒBlog-City ä¾é  Blue Dragon Servlet 引擎åQˆCFML 引擎åQ‰å’Œæ•°æ®åº“。ä×o人惊讶的是,所有这些èÊY仉™ƒ½å®¿ä¸»åœ¨è¿è¡?Red Hat Linux 的相当è€çš„ P3 æœºå™¨ä¸Šã€‚è¿™å°æœºå™¨å…·æœ‰å•个硬盘和 512MB 内存åQŒè¿™å¯¹äºŽ˜q‡åŽ»çš„è´Ÿè½½æ¥è¯´æ˜¯­‘›_¤Ÿå¼ºå¤§çš„,但它正在承å—䏿–­å¢žé•¿çš„负载。Blog-City çš„è¿ä½œæ–¹å¼å¾ˆæˆåŠŸåQŒä½†å…¶èµ„æºé™åˆ¶å´æˆäº†å…¶æˆåŠŸèµ\上的¾lŠè„šçŸŸë€‚å°½½Ž¡å¦‚此,˜q™å°±æ˜¯æœªæ¥è¿˜è¦ç‘ô¾l­ä‹É用一ŒD‰|—¶é—´çš„æ‰€æœ‰ç¡¬ä»¶ã€?/P>

问题定义

整个˜q‡ç¨‹çš„第一步是¼‹®å®š½H然出现应用½E‹åºå‡æ…¢çš„原因。首先我们怀疑的对象是垃圾收集。正如我们在 本专æ çš„上月文章 ä¸­æ‰€è®ø™¿°çš„é‚£æ øP¼Œ¼‹®å®šåžƒåœ¾æ”‰™›†å’Œå†…存利用问题是å¦å¯¹åº”用½E‹åºäº§ç”Ÿè´Ÿé¢å½±å“的最å®ÒŽ(gu¨©)˜“çš„æ–¹å¼æ˜¯åQŒè®¾¾|?-verbose:gc JVM 选项åQŒåƈ‹‚€æŸ¥æ—¥å¿—è¾“å‡ºã€‚å› æ­¤æˆ‘ä»¬é‡æ–°å¯åŠ¨åº”ç”¨ç¨‹åºï¼Œæ‰“开冗长的垃圾收集日志选项åQŒç„¶åŽè€å¿ƒåœ°ç­‰å¾…应用程åºçš„æ€§èƒ½é™ä½Žã€‚我们的è€å¿ƒæ¢æ¥çš„æ˜¯éžå¸¸è¯¦ç»†çš„垃圾收集日志文件ã€?

从对日志文äšg的最åˆåˆ†æžä¸­çœ‹ï¼Œåœ¨è¿™ä¸€åº”用½E‹åºä¸­åžƒåœ¾æ”¶é›†çš„瓉™¢ˆæ˜¯æ˜¾è€Œæ˜“è§çš„。秿Uè¿¹è±¡åŒ…æ‹¬åžƒåœ¾æ”¶é›†çš„é¢‘çŽ‡ã€æŒ¾l­æ—¶é—´å’Œæ€ÖM½“效率都已表明˜q™ä¸€ç‚V€‚高于普通垃圾收集频率的常è§åŽŸå› æ˜¯ï¼Œå †çš„å¤§å°åˆšå¥½­‘³ä»¥é€‚åº”æ‰€æœ‰å½“å‰æ­£åœ¨ä‹É用的˜q行对象åQŒæ— æ³•适应新的正被创å¾çš„å¯¹è±¡ã€‚è™½ç„¶åº”ç”¨ç¨‹åºæ¶ˆè€—大é‡å †å¯èƒ½æœ‰è®¸å¤šåŽŸå› ï¼Œä½†ä¸»è¦åŽŸå› å¯èƒ½æ˜¯æ²¡æœ‰­‘›_¤Ÿå†…存而导致垃圾收集器˜q行åQŒå› ä¸ºå®ƒè®¾æ³•满èƒö当å‰éœ€è¦ã€‚æ¢å¥è¯è¯ß_¼Œåº”用½E‹åºè¯•å›¾åˆ†é…æ–°å¯¹è±¡ï¼Œä½†å¤±è´¥äº†åQŒå¦‚果失败的è¯ï¼Œž®†è§¦å‘垃圾收集程åºã€‚如果垃圾收集失败而无法æ¢å¤èƒö够内存,它将˜q«ä‹Éå¦ä¸€ä¸ªèбè´ÒŽ(gu¨©)›´å¤§çš„垃圾攉™›†½E‹åºå‘生。å³ä½?GC æ¢å¤äº†èƒö够的½Iºé—´æ¥æ»¡­‘³çž¬é—´éœ€æ±‚,å¯ä»¥è‚¯å®šçš„æ˜¯åQŒåœ¨åº”用½E‹åº½E‹åºå¦ä¸€‹Æ¡åˆ†é…失败,触å‘å¦ä¸€ä¸?GC 之å‰åQŒæ—¶é—´ä¸ä¼šå¾ˆé•Ñ€‚因此,应该å…Ïx³¨é‡å¤æ‰«æ½Iºé—²å †ç©ºé—´çš„æ— æ•ˆä»ÕdŠ¡åQŒè€Œä¸æ˜¯æœåŠ¡äºŽåº”ç”¨½E‹åºçš?JVMã€?/P>

应用½E‹åºé€æ­¥æ¶ˆè€—所有å¯ç”¨çš„堆空间å¯èƒ½æœ‰è®¸å¤šåŽŸå› åQŒä½†å¦‚果有更多内存的è¯ï¼Œä¸´æ—¶è§£å†³æ–ÒŽ(gu¨©)¡ˆž®±æ˜¯é…置更大的堆。å‡è®‘Öº”ç”¨ç¨‹åºæ²¡æœ‰å†…存泄æ¼ï¼ˆæˆ–者也ž®±æ˜¯æˆ‘们常说的“无æ„识åœîC¿ç•™å¯¹è±¡â€ï¼‰åQŒå®ƒ?y¨­u)®†æ‰¾åˆîC¸€ä¸ªâ€œè‡ªç„¶â€çñ”别的堆消耗,在这个çñ”别中åQŒGC ž®†èƒ½å¤Ÿå¾ˆé€‚应地得到维æŒï¼ˆé™¤éžå¯¹è±¡åˆ›å¾çš„速度˜q‡å¿«åQŒä»¥è‡?GC æ€ÀL˜¯å¤„于赛跑状æ€ï¼‰ã€‚在˜q™ç§æƒ…å†µä¸‹ï¼Œä»¥åŠæ— æ„识地ä¿ç•™å¯¹è±¡çš„æƒ…况下åQŒæˆ‘们需è¦å¯¹åº”用½E‹åºåšä¸€äº›å˜åŠ¨ï¼Œä»¥ä¾¿èŽ·å¾—æŸäº›æ”¹è¿›ã€?/P>

回页�/FONT>


å¦‚æžœä»…ä»…æ˜¯è¿™æ øP¼Œé‚£å°±å¤ªç®€å•了

é—æ†¾çš„æ˜¯åQŒæˆ‘们必™å»é¢å¯¹ä¸¥é…ïLš„现实因素——正在è¿è¡Œçš„æœºå™¨åªæœ‰ 512 MB 内存。更¾pŸçš„æ˜¯ï¼Œæˆ‘们必须与数æ®åº“和其他è¿è¡Œåœ¨æœºå™¨ä¸­çš„˜q›ç¨‹å…׃ín该空间。è¦å®Œæ•´ç†è§£˜q™ä¸€ç‚¹äؓ什么至关é‡è¦ï¼Œé¦–å…ˆæ‚(zh¨¨n)¨å¿…™åÀL˜Ž¼‹®ç†è§£åžƒåœ¾æ”¶é›†çš„基本知识åQŒä»¥åŠå®ƒå¦‚何与底层æ“作系¾lŸè¿›è¡Œäº¤äº’ã€?/P>

虚拟内存ä¸å†æ˜¯çµä¸¹å¦™è?/STRONG>

æ“作¾pÈ»Ÿå·²ç»ä½¿ç”¨è™šæ‹Ÿå†…存许多òq´äº†ã€‚正如æ?zh¨¨n)¨æ‰€çŸ¥é“的,虚拟内存使æ“作系¾lŸçš„内存看è“væ¥æ¯”实际的内存è¦å¤šï¼Œ˜q™å…许计½Ž—机˜q行那些所需内存比å¯ç”¨ç‰©ç†å†…存更大的½E‹åºåQŒä¸ä½¿ç”¨å†…存的应用程åºéƒ¨åˆ†å°†ä¿å­˜åœ¨ç£ç›˜ä¸Šã€‚äØ“äº†è¿›ä¸€æ­¥ç®€åŒ–ï¼Œæ“作¾pÈ»ŸåŒæ—¶æŒ‰é¡µ½Ž¡ç†å†…å­˜ã€‚é¡µé€šå¸¸åŒ…å« 512 字节åˆ?8 KBåQŒæ‰€æœ‰é¡µçš„组åˆå°±¾l„æˆäº†ä¸€ä¸ªè™šæ‹Ÿåœ°å€½Iºé—´ã€‚æ“作系¾lŸç»´æŒä¸€ä¸ªé¡µè¡¨ï¼Œç”¨äºŽå‘Šè¯‰æ“作¾pÈ»Ÿå¦‚何映射虚拟地å€åˆ°ç‰©ç†åœ°å€ã€‚当应用½E‹åºè¦æ±‚æŸä¸ªå†…å­˜ä½ç½®çš„内å®ÒŽ(gu¨©)—¶åQŒæ“作系¾lŸï¼ˆæˆ–硬ä»Óž¼‰ž®†è¯†åˆ«åŒ…å«è™šæ‹Ÿåœ°å€çš„页é¢ã€‚ç„¶åŽç¡®å®šè¯¥™åµé¢æ˜¯å¦åœ¨å†…存中åQŒå¦‚æžœä¸åœ¨ï¼Œž®†ä¼šæŠ¥å‘Š ™åµé¢é”™è¯¯ã€‚但是有许多¿Uæ–¹å¼æ¥å¤„熙åµé¢é”™è¯¯åQŒæœ€¾lˆçš„¾l“果是,™åµé¢å¿…须从ç£ç›˜è²å…¥åˆ°å†…存中。这样应用程åºå°±å¯ä»¥è®‰K—®åˆ°æœ‰æ•ˆè™šæ‹Ÿåœ°å€çš„内å®V€?

如果相关对象æ€ÀL˜¯åœ¨å†…存的åŒä¸€™åµé¢ä¸Šèšåˆï¼Œé‚£ä¹ˆ GC 的连¾l­å·¥ä½œå¾ˆå¯èƒ½å‡ºçŽ°å›°éš¾ã€‚ä½†æ˜¯çŽ°å®žä¸–ç•Œä¸­åQŒç›¸å…›_¯¹è±¡å¾ˆž®‘(如果有的è¯ï¼‰å‡ºçްèšåˆçŽ°è±¡ã€‚å®žé™…ç»“æžœæ˜¯åQŒä¾é è™šæ‹Ÿå†…存的¾pÈ»Ÿž®†å¯¼è‡´æ“作系¾lŸå°†™åµä»Žå†…存中æ¢å…¥å’Œæ¢å‡ºåQŒå› ä¸ºå®ƒæ ‡è®°ç„¶åŽåºŸå¼ƒå †ç©ºé—ß_¼Œè€Œå½“èšåˆçŽ°è±¡å‘生æ—Óž¼ŒGC ž®†å¾ˆå¤šæ—¶é—´èŠ±åœ¨ç­‰å¾…é¡µé¢ä»Ž¼‚盘æ¢å…¥è€Œä¸æ˜¯å®žé™…æ¢å¤å†…存上。因此,应用½E‹åºæ­£åœ¨½{‰å¾… GCåQŒè€?GC 正在½{‰å¾…¼‚盘åQŒå…¶é—´æœªå®Œæˆä»ÖM½•真正的工作。由于本¾pÈ»Ÿåªæœ‰ä¸€ä¸ªç£ç›˜ï¼Œòq¶ä¸”å®ƒè¿˜éœ€è¦æ”¯æŒæ•°æ®åº“åQŒå› æ­¤æˆ‘们在解决问题时处于两隑֢ƒåœ°ã€‚一斚w¢åQŒæˆ‘们需è¦å¢žåŠ å†…å­˜æ•°é‡ï¼Œ˜q™æ ·æˆ‘们å¯ä»¥å‡å°‘ GC 的频率,但å¦ä¸€æ–šw¢åQŒæˆ‘们还需è¦ç¡®ä¿æ•°æ®åº“的完好è¿è¡Œï¼Œè€Œæ•°æ®åº“也是内存的消耗大戗÷€‚因此,我们需è¦äº†è§£åº”ç”¨ç¨‹åºæ‰€éœ€çš„æœ€ž®å†…存数é‡ã€?/P>

正如我们在上月看到的åQŒåœ¨å†—é•¿çš?GC 日志中这一信æ¯å¯ä»¥å¾ˆå®¹æ˜“得刎ͼŒæ— éœ€ä¸ø™¿™ä¸€ä¿¡æ¯è€Œæ‰«ææ•´ä¸ªæ—¥å¿—,我们使用å…è´¹çš?JTune 工具åQˆè¯·å‚阅 å‚考资æ–?/FONT>åQ‰æ¥è§£é‡Šå†—é•¿çš?GC 日志。图 1 昄¡¤ºäº†ç»˜q‡åžƒåœ¾æ”¶é›†ä¹‹åŽçš„内存利用情况åQŒå…¶ä¸­æˆ‘们将 -Xmx 讄¡½®ä¸?256 MBã€?


å›?1. 垃圾攉™›†ä¹‹åŽçš„内存利用情å†?/B>
å›?1. 垃圾攉™›†ä¹‹åŽçš„内存利用情å†? src=


回页�/FONT>


åˆ†æž verbose:gc 输出

在图 1 中,è“色部分表示部分 GC。橙色区域表½Cºå®Œæ•´çš„ GCåQŒè€Œç²‰è‰²çŸ©å½¢è¡¨½CÞZ¸¤ä¸ªå®Œæ•?GC 在它们之间少于一毫秒之内已ç»å‘生的堆利用情况。从¾l“果中我们看刎ͼŒòq›_‡æ¯?0.257 ¿U’有 12,823 ‹Æ¡æ¸…除。æ€Õd…±æœ?345 ‹Æ¡å®Œæ•´çš„垃圾攉™›†å’?44 ‹Æ¡ç´§æŒ¨ç€çš„垃圾收集。完整垃圾收集的òq›_‡æŒç®‹æ—‰™—´æ˜?7.303 ¿U’,¾l“果表明æœ?9.36% çš„è¿è¡Œæ—¶é—´èŠ±è´¹åœ¨åžƒåœ¾æ”‰™›†½E‹åºä¸Šã€‚虽然这个值å高,它ä»ç„¶ä¿æŒåœ¨ 10% 的正常水òq³ä¹‹å†…。因此,在本例中åQŒGC 是系¾lŸçš„¾Jé‡è´Ÿæ‹…但还没有辑ֈ°ä¸¥é‡çš„地步。真正的问题是存在内存泄æ¼ï¼Œ˜q™ä¸€ç‚¹å¯ä»¥ä»Žæ€ÖM½“ä¸Šå †åˆ©ç”¨çŽ‡ä¸æ–­å¢žé•¿çš„­‘‹åŠ¿çœ‹å‡ºæ¥ã€?/P>

å³ä‹Éå†…å­˜æ³„æ¼æ¶ˆè€—了 50 MB 内存åQŒå®ƒä¹Ÿåº”该是¾l过很长一ŒD‰|—¶é—´åŽæ‰å‘生,˜q™ä‹É得内存泄æ¼åœ¨è¾ƒçŸ­çš„æµ‹è¯•中很少会引人注æ„。内存泄æ¼çš„实际¾l“果是,它把 JVM 的内存消耗推动到æŸä¸ªç‚¹ï¼Œåœ¨è¯¥ç‚¹å®ƒå¼ø™¿« JVM åQˆä»Žè€Œå¼º˜q«æ“作系¾lŸï¼‰æ¶ˆè€—内存,它强˜q«å¯åŠ¨åˆ†™åüc€‚图 2 ž®Þp¯æ˜Žäº†˜q™ä¸€ç‚V€‚æ³¨æ„æ­£å¥½åœ¨ 55,000 ¿U’æ ‡è®îC¹‹åŽï¼Œæ¯ä¸€ GC 周期的挾l­æ—¶é—´ä¸­å†…存消耗çªç„¶åœ°æŒç®‹å¢žåŠ ã€?/P>
å›?2. GC æŒç®‹æ—‰™—´
å›?2. GC æŒç®‹æ—‰™—´

如æ?zh¨¨n)¨æ‰€æƒ»I¼Œç”׃ºŽåžƒåœ¾æ”‰™›†çš„é˜»å¡žå°†å¯ÆD‡´¾pÈ»Ÿåªæœ‰æ›´å°‘的时间æ¥åˆ†é…¾l™ç”¨æˆïLº¿½E‹ï¼Œå› æ­¤ç”¨æˆ·å“应开始增加。在日志的过åŽ?10,000 ¿U’中åQŒæˆ‘们看到毋ơ完全收集(æ€Õd…± 15 ‹Æ¡ï¼‰èŠÞp´¹æ—‰™—´­‘…过äº?30 ¿U’,òq›_‡æŒç®‹æ—‰™—´å¤§çº¦ 70 ¿U?—â€?˜q™å¯¼è‡´è¶…˜q?10% çš„å¤„ç†æ—¶é—´åˆ†é…给完全 GC。部分收集(˜q™é‡Œåˆšå¥½­‘…过äº?1000 ‹Æ¡ï¼‰æ— æ³•正常工作åQŒåã^凿¯‹Æ¡è¯·æ±‚耗时 1.24 ¿U’,˜qœé«˜äºŽä»¥å‰?11,800 ‹Æ¡æ¸…除中的åã^å?0.25 ¿U’ã€?/P>

分代攉™›†

æœ¬æ–‡ä¸æ¶‰åŠå¤ªæ·Þqš„¾l†èŠ‚åQˆè¯·å‚阅 å‚考资æ–?/FONT>åQŒèŽ·å–分ä»?GC 的详¾l†æ˜qŽÍ¼‰åQŒåˆ†ä»£å †½Iºé—´äº§ç”Ÿäº†â€œå¹´è½ Z€å’Œâ€œå¹´è€â€å¯¹è±¡ï¼Œå®ƒä»¬ä½äºŽåˆ†å¼€çš„å †½Iºé—´ä¸­ã€‚在本酾|®ä¸­åQŒå¹´è½Õd’Œòq´è€åˆ†ä»£ç©ºé—´å¯ä»¥é€šè¿‡ä¸åŒçš?GC ½Ž—法和策略楾l´æŒåQŒä»¥æé«˜ GC 的整体性能ã€?

一¿Uè¿™æ ïLš„½{–略是,˜q›ä¸€æ­¥å°†òq´è½»åˆ†ä»£åˆ’分为创建空é—ß_¼Œ¿UîCØ“ EdenåQŒä»¥åŠæ®‹å­˜ï¼ˆsurvivoråQ‰ç©ºé—ß_¼Œç”¨äºŽòq¸å­˜ä¸€ä¸ªæˆ–者多个收集的òq´è½»å¯¹è±¡ã€‚如果在 Eden 中有­‘›_¤Ÿçš„内存æ¥é€‚应新对象创建的è¯ï¼Œ˜q™ä¸€èˆ¬èƒ½å·¥ä½œæ­£å¸¸ã€‚å¦‚æžœä¸æ˜¯è¿™¿U情况,那么对象å¯ä»¥åœ¨å¹´è€å¯¹è±¡ç©ºé—´ä¸­åˆ›å¾ã€‚åŒæ øP¼Œå¦‚æžœŒD‹å­˜½Iºé—´­‘›_¤Ÿçš„è¯åQŒé‚£ä¹ˆå¯¹è±¡å°†¿UÕd…¥òq´è€åˆ†ä»£ç©ºé—´ã€‚我们将使用˜q™äº›äº‹å®žæ¥å¸®åŠ©è°ƒä¼˜é‡åˆ°çš„问题ã€?/P>

回页�/FONT>


å‡å°‘完全攉™›†çš„æ¬¡æ•?/FONT>

Blog-City 所¼„°åˆ°çš„难题是在æŸä¸€éšæœºç‚¹å‡ºçŽ°é•¿çš„æš‚åœæ—¶é—´ã€‚一旦应用程åºå¯åŠ¨å‡ºçŽ°é—®é¢˜ï¼Œä¸é‡æ–°å¯åŠ¨æœºå™¨çš„è¯ï¼Œž®±æ— æ³•返回跟ítªã€‚由于长旉™—´æš‚åœçš„现象直接与长的 GC 相关åQŒæˆ‘们考虑如果ž®†å¯¹è±¡ä¿æŒåœ¨òq´è½»åˆ†ä»£æ¥å‡ž®‘完å…?GC 的次数。由于完å…?GC 的代价如此之大,在年è½Õdˆ†ä»£æ”¶é›†æ›´å¤šå¯¹è±¡èƒ½å¤Ÿå¾—åˆ°æ›´çŸ­çš„æš‚åœæ—‰™—´ã€‚è¦å®Œæˆ˜q™ä¸€ä»ÕdŠ¡åQŒæˆ‘ä»¬è°ƒæ•´äº†ä¸€äº›åžƒåœ¾æ”¶é›†å‚æ•ŽÍ¼ŒåŒ…括 ŒD‹å­˜æ¯”率åQˆsurvivor ratioåQ?/I>å’?期é™é˜ˆå€û|¼ˆtenuring thresholdåQ?/I>ã€?

ŒD‹å­˜æ¯”率用于讄¡½®ä¸Žå¹´è½Õdˆ†ä»£ç©ºé—´æ€ÖM½“大å°ç›¸å…³çš„æ®‹å­˜ç©ºé—´çš„大å°ã€‚如果残存比率设¾|®äØ“ 8åQˆIntel 的默认å€û|¼‰åQŒé‚£ä¹ˆæ¯ä¸€ŒD‹å­˜½Iºé—´ž®†æ˜¯ Eden ½Iºé—´çš?1/8 大å°ã€‚å¦ä¸€¿Uè€ƒå¯Ÿå®ƒçš„æ–¹å¼æ˜¯ï¼Œòq´è½»åˆ†ä»£ž®†è¯¥ Eden ½Iºé—´åˆ’分ä¸?10 个相åŒå¤§ž®çš„å€û|¼Œè¯?Eden ž®†åˆ†é…其中的 8 个,æ¯ä¸€ä¸ªæ®‹å­˜ç©ºé—´çš„大å°ä¸?1ã€?/P>

我们的å‡è®¾æ˜¯åQŒé€šè¿‡å‡å°‘ŒD‹å­˜æ¯”率åQŒæˆ‘们å¯ä»¥å‡ž®‘由于残存空间中½Iºé—´çš„缺ä¹ï¼Œå¯¹è±¡˜q‡æ—©åœ°è¢«æå‡ä¸ºå¹´è€åˆ†ä»£çš„几率。å¦ä¸€¿U方法是增加期é™é˜ˆå€û|¼Œ˜q™æ ·çš„è¯åQŒå¯¹è±¡åœ¨æå‡ä¹‹å‰ž®†éœ€è¦ä¿ç•™æ›´å¤šçš„ GC 事äšg。本瀘q™ä¸ªæƒÏx³•åQŒBlog-City ž®†è®¾¾|®æ›´æ”¹äØ“ -XX:SurvivorRatio=4 åQŒç„¶åŽé‡æ–°å¯åЍã€?

é€‰æ‹©ä½Žæš‚åœæ—¶é—´çš„垃圾攉™›†½Ž—法

ç”׃ºŽ˜q™æ¬¡æŠ€æœ¯è°ƒä¼˜çš„目标之一是凞®‘æš‚åœæ—¶é—ß_¼Œæˆ‘们军_®šæŠ›å¼ƒé»˜è®¤çš„啾U¿ç¨‹ã€æ ‡è®°æ¸…扫的垃圾攉™›†½E‹åºã€‚我们选择通过标志 XX:+UseParallelGC æ¥é‡‡ç”¨åÆˆè¡Œæ‹·è´æ”¶é›†ç¨‹åºã€‚åŒæ øP¼Œæœ‰å…³å®žé™…½Ž—法的细节å¯ä»¥åœ¨ Resources中找刎ͼŒ˜q™é‡Œéœ€è¦æä¸€ä¸‹çš„æ˜¯ï¼Œ˜q™ä¸€æ ‡å¿—调用了一个多¾U¿ç¨‹æ”‰™›†½E‹åºã€‚线½E‹çš„æ•°é‡è®„¡½®ä¸?CPU 的数é‡ã€‚基于这一事实åQŒäº†è§£äؓ什么啾U¿ç¨‹òq¶è¡Œæ‹¯‚´åžƒåœ¾æ”‰™›†½E‹åºè¦æ¯”传统的标记清扫算法工作更好是很困隄¡š„åQŒä½†æ˜¯ä»Žå®žé™…观察中å¯ä»¥ä½“会到æä¾›äº†æŸäº›æ€§èƒ½ä¸Šçš„优势ã€?

å›?3 和图 4 的输出展½CÞZº†ä½¿ç”¨æ ‡å¿— -XX:SurvivorRatio=4 +XX:+UseParallelGC -server -Xmx256M ˜q行时的¾l“æžœã€?


å›?3. æ–°é…¾|®ä¸‹çš„内存ä‹É用情å†?/B>
å›?3. æ–°é…¾|®ä¸‹çš„内存ä‹É用情å†? src=

¾l“果图表昄¡¤ºäº†æ˜Žæ˜„¡š„ä¸åŒã€‚虽然ä»ç„¶æœ‰ä¸€ä¸ªå†…存漋zžã€‚内存消耗的æ€ÀL•°ç›¸æ¯”å‰ä¸€ä¸ªå›¾å·²ç»æ˜¯å¤§å¤§é™ä½Žäº†ã€‚GC æŒç®‹æ—‰™—´çš„快速比较歽CÞZº†òq´è½»åˆ†ä»£å’Œå¹´è€åˆ†ä»£çš„æ€ÖM½“ GC æŒç®‹æ—‰™—´çš„æ˜Žæ˜‘Ö‡ž®‘ã€?/P>
å›?4. æ–°é…¾|®ä¸‹çš?GC æŒç®‹æ—‰™—´
å›?4. æ–°é…¾|®ä¸‹çš?GC æŒç®‹æ—‰™—´

有æ„çš„ã€æ— æ„çš„å¯¹è±¡ä¿æŒ

ç”׃ºŽåº”用½E‹åºæ˜¯ä¾é å†…存的åQŒè·Ÿítªå†…存泄æ¼åƈ消除它们已ç»å˜å¾—­‘Šæ¥­‘Šé‡è¦ã€‚在本例中,用于支挾~“å­˜½{–ç•¥çš„ç»„ä»¶å†³å®šäº†ä¸»è¦æ¼æ´žçš„æ¥æºã€‚从最åŽçš„å†…å­˜åˆ†æžæƒ…况æ¥çœ‹åQˆå›¾ 3åQ‰ï¼Œè™½ç„¶æ¶ˆé™¤äº†ä¸»è¦å†…存泄æ¼ï¼Œæˆ‘们å¯ä»¥çœ‹åˆ°ä»æœ‰å¦ä¸€ä¸ªâ€œä½Ž¾U§åˆ«çš„â€çš„æ¼æ´žåQŒä½†˜q™ä¸ªæ¼æ´žæ¯”较?y¨­u)®ï¼Œå› æ­¤å®ƒåœ¨ä¸‹ä¸€ç‰ˆæœ¬å‘布之å‰å¯ä»¥å¿½ç•¥ã€?/P>

回页�/FONT>


¾l“æŸè¯?/FONT>

本文æå‡ºäº†è®¸å¤šæŒ‘战。首先,我们正在调优一个现实中的应用程åºï¼Œ˜q™æ„å‘³ç€æ›´æ”¹ä¼šå—到很多é™åˆ¶ã€‚第二个挑战是,˜q™é¡¹ä»ÕdŠ¡æ˜¯ä‹Éç”?IRC èŠå¤©å®¤è¿œ½E‹æ“控的。èŠå¤©å®¤ä¸æä¾›ä“Q何çñ”别或质é‡çš„相互通信åQŒè€Œé€šä¿¡åœ¨è¿™¿U类型的ä»ÕdŠ¡ä¸­å¾€å¾€æ˜¯å¿…éœ€çš„ã€‚åœ¨æœ¬ä¾‹ä¸­ï¼Œå›¢é˜Ÿå·²ç»ä¹ æƒ¯äº†èŠå¤©å®¤çš„真实性,òq¶èƒ½é€šè¿‡˜q™ç§çœŸå®žæ€§æ¯«æ— ä“Q何阻¼„地工作ç€ã€?/P>

最åŽä¹Ÿæ˜¯æœ€å›°éš¾çš„æŒ‘战是我们å—硬件的é™åˆ¶ã€‚由于多¿U原因,我们ä¸å¯èƒ½äØ“¾pÈ»Ÿæ·ÕdŠ æ–°ç¡¬ä»¶ã€‚å…¶ä¸­æœ€å¤§çš„é—®é¢˜æ˜¯ç³»¾lŸä¸­ç‰©ç†å†…存的数é‡ï¼Œè€?JVM å’?MySQL 需è¦å¤§é‡çš„内存。但是,通过¾pÈ»Ÿåœ°é€ä¸€åº”用许多更改åQŒåƈ度é‡å®ƒä»¬å¯¹ç³»¾lŸäñ”生的影å“åQŒæˆ‘们å¯ä»¥é€æ­¥åœ°æ”¹˜q›æ€ÖM½“¾pÈ»Ÿæ€§èƒ½ã€?/P>

回页�/FONT>


å‚考资æ–?



回页�/FONT>


作者简�/FONT>

Jack Shirazi �JavaPerformanceTuning.com的董事和 Java Performance Tuning, 2nd Edition (O'Reilly) 一书的作者�


Kirk Pepperdine is æ˜?Java Performance Tuning.com 的首席技术官åQˆChief Technical OfficeråQŒCTOåQ‰ï¼Œ˜q‡åŽ» 15 òq´æ¥ä»–一直专æ”Õd¯¹è±¡æŠ€æœ¯å’Œæ€§èƒ½è°ƒä¼˜ã€‚Kirk æ˜?Ant Developer's Handbook (MacMillan) 一书的åˆè‘—者ã€?/P>



jacky 2005-12-29 13:56 å‘表评论
]]>
å…Ïx³¨æ€§èƒ½: 谈论垃圾[转]http://www.tkk7.com/jacky/articles/25871.htmljackyjackyThu, 29 Dec 2005 05:55:00 GMThttp://www.tkk7.com/jacky/articles/25871.htmlhttp://www.tkk7.com/jacky/comments/25871.htmlhttp://www.tkk7.com/jacky/articles/25871.html#Feedback0http://www.tkk7.com/jacky/comments/commentRss/25871.htmlhttp://www.tkk7.com/jacky/services/trackbacks/25871.html

å…Ïx³¨æ€§èƒ½: 谈论垃圾

æ‚(zh¨¨n)¨çŸ¥é“垃圾收集器在干什么å—åQ?/P> developerWorks
文档选项
ž®†æ­¤™åµä½œä¸ºç”µå­é‚®ä»¶å‘é€?src="http://www.ibm.com/i/v14/icons/em.gif"

ž®†æ­¤™åµä½œä¸ºç”µå­é‚®ä»¶å‘é€?/FONT>

未显½Cºéœ€è¦?JavaScript 的文档选项


å¯ÒŽ(gu¨©)­¤™å늚„评ä­h(hu¨¢n)

帮助我们改进˜q™äº›å†…容


¾U§åˆ«: åˆçñ”

Jack Shirazi, 董事, JavaPerformanceTuning.com
Kirk Pepperdine, 首席技术官, JavaPerformanceTuning.com

2004 òq?5 æœ?01 æ—?/P>

æ‚(zh¨¨n)¨çš„应用½E‹åºæ˜¯å¦¾l常出现 out-of-memory 错误åQŸç”¨æˆäh˜¯å¦æ„Ÿå—到å“应旉™—´æœ‰äº›ä¸ç¨³å®šï¼Ÿåº”用½E‹åºæ˜¯å¦åœ¨ç›¸å½“长的时间内å˜å¾—没有å“应åQŸåº”用程åºçš„æ€§èƒ½æ˜¯å¦æ˜‘Ö¾—˜qŸç¼“了?如果对ä“Q何一个问题的回答是肯定的åQŒé‚£ä¹ˆæ?zh¨¨n)¨å¾ˆå¯èƒ½é‡åˆîCº†åžƒåœ¾æ”‰™›†çš„问题了。先别进行优化,且å¬å?JavaPerformanceTuning.com çš?Jack Shirazi å’?Kirk Pepperdine æ¥è§£é‡Šå¦‚何识别垃圾收集问题,òq¶ç”±æ­¤å¸®åŠ©æ?zh¨¨n)¨å›žç­”˜q™ä¸ªé—®é¢˜åQšæ?zh¨¨n)¨çŸ¥é“垃圾攉™›†å™¨åœ¨òq²ä»€ä¹ˆå—åQ?/BLOCKQUOTE>

许多开å‘äh员认为,内存½Ž¡ç†è‡›_¤šæ˜¯å¼€å‘业务逻辑的主è¦ä“Q务之外的一™å¹ä¸é‡è¦çš„å·¥ä½?—â€?直到业务逻辑ä¸èƒ½åƒé¢„期的或者测试时那样执行得好。出现这¿U情冉|—¶åQŒå°±éœ€è¦çŸ¥é“哪里出错了åŠå…¶åŽŸå› åQŒè¿™æ„味ç€è¦ç†è§£åº”用程åºå¦‚何与底层计算资æºåQˆç‰¹åˆ«æ˜¯å†…å­˜åQ‰è¿›è¡Œäº¤äº’。ç†è§£åº”用程åºå¦‚ä½•åˆ©ç”¨å†…å­˜çš„æœ€å¥½æ–¹å¼æ˜¯è§‚察垃圾攉™›†å™¨çš„行动ã€?/P>

ä¸ÞZ»€ä¹ˆæˆ‘的应用程åºä¸˜qžè¯äº†ï¼Ÿ

Java 虚拟æœÞZ¸­æœ€å¤§çš„一个性能问题是应用程åºçº¿½E‹ä¸ŽåŒæ—¶˜q行çš?GC 的互斥性。垃圾收集器è¦å®Œæˆå…¶å·¥ä½œåQŒéœ€è¦åœ¨ä¸€ŒD‰|—¶é—´å†…防止所有其他线½E‹è®¿é—®å®ƒæ­£åœ¨å¤„ç†çš„å †½Iºé—´åQˆå†…存)。按 GC 的术语,˜q™æ®µæ—‰™—´¿UîCؓ“stop-the-worldâ€ï¼Œòq¶ä¸”åQŒæ­£å¦‚å…¶å字所表明的,在垃圾收集器努力工作æ—Óž¼Œåº”用½E‹åºæœ‰ä¸€ä¸ªæ€¥åˆ¹è½¦ã€‚幸˜q的是,˜q™ç§æš‚åœé€šå¸¸æ˜¯å¾ˆçŸ­çš„åQŒå¾ˆéš‘Ö¯Ÿè§‰åˆ°åQŒä½†æ˜¯å¾ˆå®ÒŽ(gu¨©)˜“惛_ƒåQŒå¦‚果应用程åºåœ¨éšæœºçš„æ—¶åˆÕd‡ºçŽ°éšæœÞZ¸”较长旉™—´çš„æš‚åœï¼Œå¯¹åº”用程åºçš„å“应性和åžåèƒ½åŠ›ä¼šæœ‰ç ´åæ€§çš„å½±å“ã€?/P>

ä¸è¿‡ GC åªæ˜¯åº”用½E‹åºå‡ºçްä¸è¿žè´¯å’Œåœé¡¿çš„一个原因。那么如何确å®?GC 对äñ”生这些问题是å¦è´Ÿæœ‰è´£ä»Õd‘¢åQŸè¦å›žç­”˜q™ä¸ªé—®é¢˜åQŒæˆ‘ä»¬éœ€è¦æµ‹é‡åžƒåœ¾æ”¶é›†å™¨çš„工作强度,òq¶å½“在系¾lŸä¸­˜q›è¡Œæ”¹å˜æ—¶ç‘ô¾l­è¿™äº›æµ‹é‡ï¼Œä»¥å®šé‡åœ°¼‹®å®šæ‰€åšçš„æ”¹å˜æ˜¯å¦æœ‰æ‰€æœŸæœ›çš„æ•ˆæžœã€?/P>

我需è¦å¤šž®‘内存?

æ™®éæŽ¥å—的信忉|˜¯åQŒåœ¨¾pÈ»Ÿä¸­æ·»åŠ å†…å­˜å°†è§£å†³è®¸å¤šæ€§èƒ½é—®é¢˜ã€‚è™½ç„¶è¿™ä¸ªåŽŸåˆ™å¯¹äº?JVM æ¥è¯´¾l常是正¼‹®çš„åQŒä½†æ˜¯å¤ªå¤šå¥½ä¸œè¥¿å¯èƒ½å¯ÒŽ(gu¨©)€§èƒ½æ˜¯æœ‰å®³çš„。因此技巧在äº?Java 应用½E‹åºéœ€è¦å¤šž®‘内存就¾l™å®ƒå¤šå°‘åQŒä½†æ˜¯ç»ä¸å¤š¾l™ã€‚问题是åQŒåº”用程åºéœ€è¦å¤šž®‘内存?对于应用½E‹åºä¸è¿žè´¯çš„æƒ…况åQŒæˆ‘们需è¦è§‚察垃圾收集行ä¸ÞZ»¥äº†è§£çœ‹å®ƒåšçš„æ˜¯å¦æ¯”所需è¦çš„æ›´å¤šã€‚这些观察将告诉我们所åšçš„æ”¹å˜æ˜¯å¦æœ‰æ‰€æœŸæœ›çš„æ•ˆæžœã€?/P>

回页�/FONT>


‹¹‹é‡ GC 的活åŠ?/FONT>

ç”Ÿæˆ GC æ—¥å¿—çš„æ ‡å‡†æ–¹å¼æ˜¯ä½¿ç”¨ -verbose:gc æ——æ ‡åQŒè®¾¾|®è¿™ä¸ªæ——æ ‡åŽåQŒåžƒåœ¾æ”¶é›†å™¨ä¼šåœ¨æ¯æ¬¡˜q行时生æˆå®ƒæ‰€åšçš„事情的汇总,一般是写入到控制å°åQˆé€šè¿‡æ ‡å‡†è¾“出或者标准错误)。许å¤?VM 支æŒä¸€ä¸ªå…è®?verbose GC 输出转å‘åˆîC¸€ä¸ªæ–‡ä»¶çš„选项。例如,åœ?Sun çš?1.4 JVM 中,å¯ä»¥ä½¿ç”¨å¼€å…?-Xloggc:filename ž®?GC 输出写到文äšg中。对äº?HP JVMåQŒè¦ä½¿ç”¨ -Xverbosegc=file 开兟뀂在本文中,我们ž®†åˆ†æž?Sun 1.4.2 å’?IBM 1.4.1 JVM æ•获çš?verbose GC 输出ã€?

使用˜q™ä¸ªæ–ÒŽ(gu¨©)³•监视内存使用的一个最大好处是它对应用½E‹åºçš„æ€§èƒ½çš„媄å“很ž®ã€‚ä¸òq¸çš„æ˜¯ï¼Œ˜q™ä¸ªè§£å†³æ–ÒŽ(gu¨©)¡ˆòq¶ä¸å®Œç¾ŽåQŒå› ä¸ø™¿™äº›æ—¥å¿—文件å¯èƒ½å˜å¾—特别大åQŒè€Œç»´æŠ¤å®ƒä»¬å¯èƒ½éœ€è¦é‡æ–°å¯åŠ?JVM。尽½Ž¡å¦‚此,˜q™ç§æŠ€æœ¯åœ¨ç”Ÿäñ”环境中ä»ç„¶æ˜¯å¯è¡Œçš„ï¼Œå› äØ“å®ƒå¯ä»¥å¸®åŠ©è¯Šæ–­åªåœ¨è¿™¿U环境中æ‰åˆ—出的性能问题ã€?/P>

更深入观�GC

-verbose:gc 旗标生æˆçš„输出根æ?JVM 厂商而ä¸åŒï¼Œä¸åŒçš„垃圾收集器选项会报告特定于该实现的信æ¯ã€‚例如,ç”?IBM JVM 生æˆçš„输出比ç”?Sun JVM 生æˆçš„输出冗长得多,è€?Sun 的输出更适åˆäºŽç”±å·¥å…·è¯Õd–。就是说åQŒæ¯ä¸€ä¸?GC æ—¥å¿—ä¼ è¾¾åŸºæœ¬ä¿¡æ¯ â€”â€?使用了多ž®‘å†…å­˜ã€æ¢å¤äº†å¤šå°‘内存ã€GC 周期用了多少旉™—´åQŒä»¥åŠåœ¨æ”‰™›†æœŸé—´æ˜¯å¦é‡‡å–了其他行动。从˜q™äº›åŸºæœ¬‹¹‹é‡ä¸­ï¼Œæˆ‘们å¯ä»¥æŽ¨æ–­å‡ºæœ‰åŠ©äºŽæ›´å¥½åœ°ç†è§£æ‰€å‘生的事情的¾l†èŠ‚ã€‚æˆ‘ä»¬è¦è®¡ç®—的统计如下所½Cºï¼š

  • 考虑的è¿è¡Œæ—¶çš„æŒ¾l­æ—¶é—?
  • 攉™›†æ€ÀL•°
  • 攉™›†é¢‘率
  • 攉™›†æ‰€ç”¨æœ€é•¿æ—¶é—?
  • 攉™›†æ‰€ç”¨æ€ÀL—¶é—?
  • 攉™›†æ‰€ç”¨åã^凿—¶é—?
  • 攉™›†çš„åã^å‡é—´éš?
  • 分é…的字节æ€ÀL•°
  • æ¯æ¬¡æ”‰™›†æ¯ç§’分é…的字节数
  • æ¢å¤çš„字节æ€ÀL•°
  • æ¯æ¬¡æ”‰™›†æ¯ç§’æ¢å¤çš„字节æ€ÀL•°

ç†è§£äº†æš‚åœæ—¶é—ß_¼Œæˆ‘们ž®±å¯ä»¥ç†è§?GC 对应用程åºä¸å“应是å¦è´Ÿæœ‰éƒ¨åˆ†æˆ–者全部责ä»ÖMº†ã€‚一¿U实现这一ä»ÕdŠ¡çš„æ–¹æ³•æ˜¯ž®†è¯¦¾l†ï¼ˆverboseåQ?GC 日志中的 GC ‹zÕdŠ¨ä¸Žç³»¾lŸé‡‡é›†çš„其他日志åQˆå¦‚ Web æœåŠ¡å™¨æ—¥å¿—ä¸­çš„è¯·æ±?backlogåQ‰ç›¸å¯¹åº”。几乎å¯ä»¥è‚¯å®šæœ€é•¿çš„ GC æš‚åœä¼šå¯¼è‡´æ•´ä¸ªç³»¾lŸå“åº”å¯æ„Ÿè§‰çš„下é™ï¼Œæ‰€ä»¥çŸ¥é“什么时候å“åº”ä¸‹é™æ˜¯å¾ˆæœ‰ç”¨çš„åQŒè¿™æ ·å°±å¯ä»¥ž®?GC ‹zÕdŠ¨ä¸Žåº”ç”¨ç¨‹åºåžå相兌™”èµäh¥ã€?/P>

å¦ä¸€¿Uå¯èƒ½çš„竞争因素是堆内存分é…å’Œæ¢å¤çš„æ¯”率åQŒç§°ä¸?churn。äñ”生大é‡ç«‹å³é‡Šæ”„¡š„对象的应用程åºé€šå¸¸ä¼šå—åˆ?churn 的拖累。更高的 churn 比率对垃圾收集器加以很大压力åQŒåˆ›é€ äº†æ›´å¤šçš„内存资æºç«žäº‰ï¼Œ˜q™åˆå¯å¯¼è‡´æ›´é•¿çš„æš‚åœæˆ–è€…å¯æ€•çš„ OutOfMemoryError ã€?

了解应用½E‹åºæ˜¯å¦é­é‡˜q™äº›é—®é¢˜çš„一个方法是‹¹‹é‡æ‰€è€ƒè™‘的整个è¿è¡Œæ—¶æœŸé—´ GC 所å ç”¨çš„æ€ÀL—¶é—´ã€‚有了这¿U计½Ž—,我们ž®±å¯ä»¥äº†è§?GC åšçš„æ˜¯å¦æ¯”它所应该åšçš„æ›´å¤šã€‚è®©æˆ‘ä»¬æŽ¨å¯¼å‡ø™¿›è¡Œè¿™¿U判断所需è¦çš„å…¬å¼ã€?/P>

回页�/FONT>


Sun GC 日志记录

æ¸…å• 1 是由 Sun 1.4.2_03 JVM ä»?-Xloggc:filename ˜q行默认的标è®?清除攉™›†å™¨æ‰€ç”Ÿæˆçš„æ—¥å¿—记录的例å­ã€‚å¯ä»¥çœ‹åˆŽÍ¼Œæ—¥å¿—™åšwžå¸¸ç²¾¼‹®åœ°è®°å½•了毋ơ所åšçš„事情ã€?


æ¸…å• 1. 使用 -Xloggc:filename æ——æ ‡çš?GC 日志记录

69.713: [GC 11536K->11044K(12016K), 0.0032621 secs]
69.717: [Full GC 11044K->5143K(12016K), 0.1429698 secs]
69.865: [GC 5958K->5338K(11628K), 0.0021492 secs]
69.872: [GC 6169K->5418K(11628K), 0.0021718 secs]
69.878: [GC 6248K->5588K(11628K), 0.0029761 secs]
69.886: [GC 6404K->5657K(11628K), 0.0017877 secs]

首先注æ„到的å¯èƒ½æ˜¯æ¯ä¸€™åÒŽ(gu¨©)—¥å¿—记录是写在一¾l„方括å·å†…的。其ä»?GC ½Ž—法åQŒå¦‚òq¶å‘攉™›†å™¨ï¼Œ å¯èƒ½ž®†ä¸€äº›å€¼åˆ†è§£äؓ更细的信æ¯ã€‚如果是˜q™ç§æƒ…况åQŒè¿™äº›è¢«åˆ†è§£çš„å€ég¼šç”±åŒ…围在嵌入的一¾l„方括å·ä¸­çš„¾l†èŠ‚æ‰€æ›¿ä»£åQŒè¿™ä½¿å·¥å…·å¯ä»¥æ›´å®ÒŽ(gu¨©)˜“地处ç†è¯¦¾l?GC 输出ã€?/P>

我们的研½I‰™¦–å…ˆä»Žåˆ†æžæ¸…å• 1 中标è®îCØ“ 69.713 的记录开始。这个标记是 JVM 开始åŽçš„秒数和毫秒数的旉™—´æˆŸë€‚在˜q™ä¸ªä¾‹å­ä¸­ï¼ŒJVM 在这ä¸?GC 周期开始之å‰è¿è¡Œäº† 69.713 ¿U’。从左到å³çš„字段为:执行的收集的¾cÕdž‹ã€GC 之å‰çš„å †ä½¿ç”¨ã€æ€Èš„堆能力和 GC 事äšg的挾l­æ—¶é—´ã€‚从˜q™ä¸ªæè¿°ä¸­æˆ‘们å¯ä»¥çœ‹å‡ºç¬¬ä¸€ä¸?GC 事äšg是一个å°çš„æ”¶é›†ã€‚在 GC 开始之å‰ï¼Œä½¿ç”¨äº?11536 Kb 的堆½Iºé—´ã€‚åœ¨å®Œæˆæ—Óž¼Œä½¿ç”¨äº?11044 KbåQŒå †èƒ½åŠ›ä¸?12016 KbåQŒè€Œæ•´ä¸ªæ”¶é›†ç”¨äº?.0032621 ¿U’。下一个事ä»Óž¼Œä¸€ä¸ªå®Œå…¨çš„ GCåQŒåœ¨ 69.717 ¿U’æ—¶æˆ–è€…ä¸Šä¸€ä¸ªå° GC 事äšgä¹‹åŽ 0.003 ¿U’时开始。注æ„,如果ž®†å° GC 事äšg的挾l­æ—¶é—´åŠ åˆ°å…¶å¼€å§‹æ—¶é—´ä¸ŠåQŒå°±ä¼šçœ‹åˆ°å®ƒåœ¨å®Œå…¨çš„ GC 开始之å‰ä¸åˆ?1毫秒¾l“æŸã€‚因此我们å¯ä»¥å¾—出结论:ž®æ”¶é›†æ²¡æœ‰æ¢å¤èƒö够的½Iºé—´åQŒè¿™¿U失败触å‘了完全çš?GC。对应用½E‹åºæ¥è¯´åQŒè¿™åƒæ˜¯ä¸€ä¸ªæŒ¾l­äº† 0.1462319 ¿U’的事äšg。让我们¾l§ç®‹¼‹®å®šå¦‚何计算其他倹{€?/P>

GC æ—¥å¿—è®°å½•çš„å‚æ•°ç¡®å®?/STRONG>

我们通过¼‹®å®šæ¯ä¸ª GC æ—¥å¿—è®°å½•ä¸­çš„å€¼çš„å‚æ•°æ¥å¼€å§‹åˆ†æžï¼š

R(n) = T(n): [ <GC> HB->HE(HC), D]

n 清å•中记录的索引åQ? 是第一个,m 是最åŽä¸€ä¸?/TD>
R(n) GC 记录
T(n) ½W?n ä¸?GC å‘生的时é—?/TD>
HB GC 之å‰å †çš„æ•°é‡
HE GC 之åŽä½¿ç”¨çš„堆数é‡
HC 堆空间的总é‡
D GC 周期的挾l­æ—¶é—?/TD>

有了˜q™äº›å®šä¹‰åQŒæˆ‘们现在å¯ä»¥æŽ¨å¯¼å‡ºç”¨äºŽè®¡ç®—å‰é¢æè¿°çš„值的公å¼ã€?/P>

回页�/FONT>


基本�/FONT>

我们è¦è®¡½Ž—çš„½W¬ä¸€ä¸ªå€¼æ˜¯æ—¥å¿—所覆盖的è¿è¡Œæ—¶æ•´ä¸ªæŒç®‹æ—‰™—´ã€‚如果è¦è€ƒè™‘æ¯ä¸€™å¹è®°å½•,那么ž®Þp¦åˆ†æžæœ€åŽä¸€™å¹è®°å½•的旉™—´æˆŸë€‚因为清å?1 åªè¡¨½Cºå…¨éƒ¨æ—¥å¿—记录的一部分åQŒæˆ‘们需è¦ä»Žæœ€åŽä¸€™å¹ä¸­æå–出第一个时间戳。尽½Ž¡å¯¹˜q™ä¸ªä¾‹å­æ¥è¯´åQŒè¿™ä¸ªæ•°å­—èƒö够精¼‹®ï¼Œä½†æ˜¯ä¸ÞZº†¾l对准确åQŒéœ€è¦åŠ ä¸Šæœ€å?GC 的挾l­æ—¶é—´ã€‚其原因是时间戳是在 GC 开始时记录的,而记录表½Cºåœ¨è®°å½•了时间戳以åŽå‘生的事情ã€?/P>

剩余值是å–记录中相应的值的æ€Õd’Œè®¡ç®—的。值得注æ„的是æ¢å¤çš„字节å¯ä»¥é€šè¿‡åˆ†æžè®°å½•中测é‡çš„关系而计½Ž—,而分é…的字节å¯ä»¥é€šè¿‡åˆ†æžå‰åŽè®°å½•‹¹‹é‡ä¹‹é—´çš„å…³¾p»è®¡½Ž—。例如,如果考虑在时间戳 69.872 å’?69.878 之间å‘现的记录对åQŒå¯ä»¥ç”¨½W¬ä¸€ä¸ªè®°å½•中 GC 之åŽå ç”¨çš„内存数é‡å‡åŽÈ¬¬äºŒä¸ªè®°å½•åœ?GC 之å‰å ç”¨çš„字节数é‡è®¡½Ž—在新的一代(generationåQ‰ä¸­åˆ†é…的字节数é‡ï¼š 6248 Kb - 5418 Kb = 830 Kb 。下é¢è¡¨ 1 展示了其他值的公å¼ã€?

è¦æ‰¾å‡ºæœ€é•¿çš„ GC æš‚åœåQŒæˆ‘们åªéœ€è¦æŸ¥çœ‹æŒ¾l­æ—¶é—´åƈå¯ÀL‰¾ D(n) åQˆè®°å½?n 的挾l­æ—¶é—ß_¼‰çš„æœ€å¤§å€¹{€?

è¡?1. ¾lŸè®¡å…¬å¼

¾lŸè®¡ 计算åQˆæ—¶é—´å•ä½è°ƒæ•´äØ“¿U’)
˜q行时挾l­æ—¶é—?/TD> RT = (T(M) + D(M)) - T(1)
ž®æ”¶é›†çš„æ€ÀL•° TMC = Sum( R(n)) 其中 GC(n) = GC
完全攉™›†çš„æ€ÀL•° TFC = Sum( R(n)) 其中 GC(n) = Full
攉™›†é¢‘率åQˆå°æ”‰™›†åQ?/TD> CFM = TMC / RT
攉™›†é¢‘率åQˆå®Œå…¨ï¼‰ CFF = TFC / RT
攉™›†çš„æ—¶é—ß_¼ˆæœ€é•¿çš„ž®æ”¶é›†ï¼‰ MAX(D(n)) for all n 其中 GC(n) = GC
攉™›†çš„æ—¶é—ß_¼ˆæœ€é•¿çš„完全攉™›†åQ?/TD> MAX(D(n)) for all n 其中 GC(n) = Full
ž®æ”¶é›†çš„æ—‰™—´åQˆæ€ÀL•°åQ?/TD> TTMC = Sum(D(n)) for all n 其中 GC(n) = GC
完全攉™›†çš„æ—¶é—ß_¼ˆæ€ÀL•°åQ?/TD> TTFC Sum(D(n)) for all n 其中 GC(n) = Full
攉™›†çš„æ—¶é—ß_¼ˆæ€ÀL•°åQ?/TD> TTC = TTMC + TTFC
ž®æ”¶é›†çš„æ—‰™—´åQˆåã^å‡ï¼‰ ATMC = TTMC / RT
完全攉™›†çš„æ—¶é—ß_¼ˆòq›_‡åQ?/TD> ATFC = TTFC / RT
攉™›†çš„æ—¶é—ß_¼ˆòq›_‡åQ?/TD> ATC = TTC / RT
攉™›†é—´éš”åQˆåã^å‡ï¼‰ Sum( T(n+1) - T(n)) / (TMC + TFC) for all n
分é…的字节(æ€ÀL•°åQ?/TD> TBA = Sum(HB(n+1) - HE(n)) 对于所æœ?n
分é…的字节(æ¯ç§’åQ?/TD> TBA / RT
分é…çš„å­—èŠ‚ï¼ˆæ¯æ¬¡æ”‰™›†åQ?/TD> TBA / (TMC + TFC)
ž®æ”¶é›†æ¢å¤çš„字节åQˆæ€ÀL•°åQ?/TD> BRM = Sum(HB(n) - HE(n)) 其中 GC(n) = GC
完全攉™›†æ¢å¤çš„字节(æ€ÀL•°åQ?/TD> BRF = Sum(HB(n) - HE(n)) 其中 GC(n) = Full
æ¢å¤çš„字节(æ€ÀL•°åQ?/TD> BRT = BRM + BRF
æ¢å¤çš„å­—èŠ‚ï¼ˆæ¯æ¬¡ž®æ”¶é›†ï¼‰ BRPM = BRM / TMC
æ¢å¤çš„å­—èŠ‚ï¼ˆæ¯æ¬¡å®Œå…¨æ”‰™›†åQ?/TD> BRPF = BRF / TMF
æ¢å¤çš„字节(ž®æ”¶é›†æ¯¿U’) BRP = BRM / TTMC
æ¢å¤çš„字节(完全攉™›†æ¯ç§’åQ?/TD> BRF = BRF / TTFC

å¯ä»¥ä»Žå…¬å¼ä¸­çœ‹å‡ºåQŒæˆ‘们ç»å¸”Rœ€è¦åˆ†åˆ«è€ƒè™‘完全 GC å’Œå° GCã€‚å° GC 与完å…?GC 有根本性的ä¸åŒåQŒä¸€èˆ¬æ¥è¯´å‰è€…至ž®‘比åŽè€…è¦å¿«ä¸€ä¸ªæ•°é‡çñ”。我们å¯ä»¥é€šè¿‡å¿«é€Ÿåˆ†æžæ¸…å?1 看出˜q™ä¸€ç‚?—â€?最长的ž®æ”¶é›†æ¯”完全攉™›†å¿?50 å€ã€?/P>

下é¢è¡?2 昄¡¤ºå¯ÒŽ(gu¨©)¸…å?1 中的å€ég‹É用表 1 中的公å¼çš„结果ã€?/P>

è¡?2. Sun GC 日志分æž

¾lŸè®¡ 计算åQˆæ—¶é—´å•ä½è°ƒæ•´äØ“¿U’)
˜q行时挾l­æ—¶é—?/TD> (69.886 + 0.0017877) - 69.713 = 0.1747877
ž®æ”¶é›†æ€ÀL•° 5
完全攉™›†æ€ÀL•° 1
攉™›†é¢‘率åQˆå°æ”‰™›†åQ?/TD> 5 / 0.1747877 = 28.6 per second
攉™›†é¢‘率åQˆå®Œå…¨ï¼‰ 1 / 0.1747877 = 5.27 per second
攉™›†æ—‰™—´åQˆæœ€é•¿çš„ž®æ”¶é›†ï¼‰ 0.0032621
攉™›†æ—‰™—´åQˆæœ€é•¿çš„完全攉™›†åQ?/TD> 0.1429698
ž®æ”¶é›†çš„æ—‰™—´åQˆæ€ÀL•°åQ?/TD> 0.0123469
完全攉™›†çš„æ—¶é—ß_¼ˆæ€ÀL•°åQ?/TD> 0.1429698
攉™›†çš„æ—¶é—ß_¼ˆæ€ÀL•°åQ?/TD> 0.1553167
ž®æ”¶é›†çš„æ—‰™—´åQˆåã^å‡ï¼‰ 7.1%
完全攉™›†çš„æ—¶é—ß_¼ˆòq›_‡åQ?/TD> 81.8%
攉™›†çš„æ—¶é—ß_¼ˆòq›_‡åQ?/TD> 88.9%
攉™›†é—´éš”åQˆåã^å‡ï¼‰ .173/5=0.0346
分é…的字节(æ€ÀL•°åQ?/TD> 3292
分é…的字节(æ¯ç§’åQ?/TD> 18834 Kb/second
分é…çš„å­—èŠ‚ï¼ˆæ¯æ¬¡æ”‰™›†åQ?/TD> 549 Kb
ž®æ”¶é›†æ¢å¤çš„字节åQˆæ€ÀL•°åQ?/TD> 3270 Kb
完全攉™›†æ¢å¤çš„字节(æ€ÀL•°åQ?/TD> 5901 Kb
æ¢å¤çš„字节(æ€ÀL•°åQ?/TD> 5901 + 3270 = 9171 Kb
æ¢å¤çš„å­—èŠ‚ï¼ˆæ¯æ¬¡ž®æ”¶é›†ï¼‰ 3270/5 = 654
æ¢å¤çš„å­—èŠ‚ï¼ˆæ¯æ¬¡å®Œå…¨æ”‰™›†åQ?/TD> 5901/1 = 5901
æ¢å¤çš„字节(ž®æ”¶é›†æ¯¿U’) 3270/0.0123469 = 264843 Kb/second
æ¢å¤çš„字节(完全攉™›†æ¯ç§’åQ?/TD> 5901/0.1429698 = 41274K/second

è¡?2 包å«ä»Žè¿™äº›çœ‹æ¥ç®€å•的日志中推½Ž—出的大é‡ä¿¡æ¯ã€‚å–决于所å…Ïx³¨çš„问题,å¯èƒ½ä¸éœ€è¦è®¡½Ž—所有这些å€û|¼Œå› äؓ其中一些值比å¦ä¸€äº›æ›´æœ‰ç”¨ã€‚对于应用程åºé•¿æ—‰™—´ä¸å“应的情况åQŒè¦å…Ïx³¨çš„æ˜¯ GC æŒç®‹æ—‰™—´å’Œè®¡æ•°ã€?/P>

回页�/FONT>


IBM GC 日志记录

ä¸?Sun 日志ä¸åŒåQŒIBM 日志特别冗长。å³ä½¿è¿™æ øP¼Œä»ç„¶éœ€è¦ä¸€ä¸ªæŒ‡å¯ég»¥å®Œå…¨ç†è§£æ‰€æä¾›çš„ä¿¡æ¯ã€‚清å?2 是这¿U?verbose:gc 日志文äšg的一部分ã€?


æ¸…å• 2. IBM JVM verbose:gc 输出

<AF[31]: Allocation Failure. need 528 bytes, 969 ms since last AF>
<AF[31]: managing allocation failure, action=1 (0/97133320) (1082224/1824504)>
  <GC(31): GC cycle started Wed Feb 25 23:08:41 2004
  <GC(31): freed 36259000 bytes, 37% free (37341224/98957824), in 569 ms>
  <GC(31): mark: 532 ms, sweep: 37 ms, compact: 0 ms>
  <GC(31): refs: soft 0 (age >= 32), weak 0, final 2, phantom 0>
<AF[31]: managing allocation failure, action=3 (37341224/98957824)>
  <GC(31): need to expand mark bits for 116324864-byte heap>
  <GC(31): expanded mark bits by 270336 to 1818624 bytes>
  <GC(31): need to expand alloc bits for 116324864-byte heap>
  <GC(31): expanded alloc bits by 270336 to 1818624 bytes>
  <GC(31): need to expand FR bits for 116324864-byte heap>
  <GC(31): expanded FR bits by 544768 to 3637248 bytes>
  <GC(31): expanded heap by 17367040 to 116324864 bytes, 47% free, ratio:0.417>
<AF[31]: completed in 812 ms>

<AF[32]: Allocation Failure. need 528 bytes, 1765 ms since last AF>
<AF[32]: managing allocation failure, action=1 (0/115394264) (930600/930600)>
  <GC(32): GC cycle started Wed Feb 25 23:08:43 2004
  <GC(32): freed 54489184 bytes, 47% free (55419784/116324864), in 326 ms>
  <GC(32): mark: 292 ms, sweep: 34 ms, compact: 0 ms>
  <GC(32): refs: soft 0 (age >= 32), weak 0, final 0, phantom 0>
<AF[32]: completed in 328 ms>

<AF[33]: Allocation Failure. need 528 bytes, 1686 ms since last AF>
<AF[33]: managing allocation failure, action=1 (0/115510592) (814272/814272)>
  <GC(33): GC cycle started Wed Feb 25 23:08:45 2004
  <GC(33): freed 56382392 bytes, 49% free (57196664/116324864), in 323 ms>
  <GC(33): mark: 285 ms, sweep: 38 ms, compact: 0 ms>
  <GC(33): refs: soft 0 (age >= 32), weak 0, final 18, phantom 0>
<AF[33]: completed in 324 ms>

æ¸…å• 2 中有三项 GC 日志记录。我ž®†ä¸ä¼šæä¾›å®Œå…¨çš„说明åQŒè€Œæ˜¯æŽ¨è一½‹‡ç”± Sam Borman 所写的很好的文章“Sensible Sanitationâ€ï¼ˆè¯·å‚é˜?å‚考资æ–?/FONT>åQ‰ã€‚对于我们的目的åQŒéœ€è¦ä¸Žåƒå¯¹ Sun JVM 的日志那æ ähލ½Ž—å‡ºåŒæ ·¾cÕdž‹çš„ä¿¡æ¯ã€‚å¥½çš„æ–¹é¢æ˜¯æœ‰ä¸€äº›è®¡½Ž—结果已¾l是现æˆçš„äº†ã€‚ä¾‹å¦‚ï¼Œå¦‚æžœåˆ†æž AF[31] åQˆäº‹ä»?31 分é…å¤ÞpÓ|åQ‰ï¼Œž®†ä¼šçœ‹åˆ° GC ä¹‹é—´çš„é—´éš”ã€æ¢å¤çš„内存数é‡ã€äº‹ä»¶çš„æŒç®‹æ—‰™—´ã€‚我们å¯ä»¥æ ¹æ®è¿™äº›æ•°å­—计½Ž—其他所需è¦çš„倹{€?



回页�/FONT>


˜q™äº›æ•°å­—有什么æ„ä¹?/FONT>

如何看待˜q™äº›æ•°å­—å–决于所è¦å¾—到的¾l“果。在许多æœåŠ¡å™¨åº”ç”¨ç¨‹åºä¸­åQŒå®ƒå½’ç»“ä¸ºç¾ƒçŸ­æš‚åœæ—¶é—ß_¼Œ˜q™åˆå½’结为凞®‘所å‘生的完全收集的æŒç®‹æ—‰™—´å’Œæ¬¡æ•°ã€‚下个月åQŒæˆ‘们将探讨如何用这些信æ¯è°ƒä¼˜æ›¾¾lå—˜q™ä¸ªé—®é¢˜å›°æ‰°çš„一个真实应用程åºã€?/P>

回页�/FONT>


å‚考资æ–?



回页�/FONT>


作者简�/FONT>

Jack Shirazi æ˜?JavaPerformanceTuning.com的董事,也是 Java Performance Tuning, 2nd Edition åQˆO'ReillyåQ?一书的作者ã€?


Kirk Pepperdine æ˜?Java Performance Tuning.com 的首席技术官åQŒåƈ且在˜q‡åŽ» 15 òq´ä¸€ç›´å…³æ³¨å¯¹è±¡æŠ€æœ¯å’Œæ€§èƒ½è°ƒä¼˜ã€‚Kirk æ˜?Ant Developer's Handbook åQˆMacMillanåQ‰ä¸€ä¹¦çš„åˆè‘—者ã€?



jacky 2005-12-29 13:55 å‘表评论
]]>
Ö÷Õ¾Ö©Öë³ØÄ£°å£º ¹ú²úÃâ·Ñ¿¨Ò»¿¨Èý¿¨ÂÒÂë| ¾Ã¾Ãer¹ú²ú¾«Æ·Ãâ·Ñ¹Û¿´8| ÑÇÖÞÃâ·ÑÊÓÆµ²¥·Å| ÖÐÎÄ×ÖÄ»ÑÇÖÞ×ۺϾþÃ| ÑÇÖÞ±¬ÈéÎÞÂëÒ»Çø¶þÇøÈýÇø| ¹ú²úAVÎÞÂë×¨ÇøÑÇÖÞA¡ÅëƬ| ÑÇÖÞ´ó³ß¶ÈÎÞÂë×¨ÇøÓÈÎï| ÖÐÎÄ×ÖÄ»ÑÇÖÞµÚÒ»| ÑÇÖÞÉ«WWW³ÉÈËÓÀ¾ÃÍøÖ·| ÑÇÖÞÖÐÎÄ×ÖÄ»ÎÞÂë²»¿¨µçÓ°| ²»¿¨Ò»¿¨¶þ¿¨ÈýÑÇÖÞ| ÑÇÖÞÂÒÂëÖÐÎÄ×ÖÄ»¾Ã¾ÃÔи¾ºÚÈË| ÑÇÖÞ¹ú²ú¾«Æ·³ÉÈË| ÑÇÖÞ¹ú²ú¾«Æ·Ò»Çø¶þÇøÈýÇø¾Ã¾Ã| ÄÚÉäÎÞÂë×¨Çø¾Ã¾ÃÑÇÖÞ| ÑÇÖÞÇøÈÕº«ÇøÎÞÂëÇø| ¹ú²ú¾«Æ·ÑÇÖÞ¸ßÇåÒ»Çø¶þÇø| ÑÇÖÞÅ·ÖÞ³ÉÈ˾«Æ·Ïã½¶Íø| ÑÇÖÞ¹ú²ú¾«Æ·Ò»Çø¶þÇø¾Ã¾Ãhs| ¾Ã¾ÃÑÇÖÞÃâ·ÑÊÓÆµ| ÑÇÖÞÃÀÅ®ÖÐÎÄ×ÖÄ»| ÑÇÖÞÌìÌÃÄÐÈËÓ°Ôº| ÑÇÖÞjizzjizzÉÙ¸¾| ´óƬÃâ·Ñ¹Û¿´92ÔÚÏßÊÓÆµÏßÊÓÆµ| ¹ú²úÄÐŮˬˬˬÃâ·ÑÊÓÆµ | ÑÇÖÞ¹ú²ú¾«Æ·ÎÞÂë³ÉÈËÆ¬¾Ã¾Ã| ÑÇÖÞ³ÉAVÈËÆ¬ÌìÌÃÍøÎÞÂë| ÑÇÖÞavÂ³Ë¿Ò»Çø¶þÇøÈýÇø| ÑÇÖÞ»ÆÉ«ÔÚÏßÊÓÆµ| ¹ú²ú91ÔÚÏß|ÑÇÖÞ| ÑÇÖÞÖÐÎÄ×ÖÄ»¾Ã¾Ã¾«Æ·ÃÛÌÒ| Å·ÃÀ¼¤Çé×ÛºÏÑÇÖÞÒ»¶þÇø| ÎÛÍøÕ¾ÔÚÏß¹Û¿´Ãâ·Ñ| aaëƬÃâ·ÑÈ«²¿²¥·ÅÍêÕû| 99¾«Æ·ÊÓÆµÃâ·Ñ¹Û¿´| 99ÈÈÔÚÏß¾«Æ·Ãâ·ÑÈ«²¿my| ¹ú²úÃâ·ÑÉü½»ÊÓÆµ| ¾«Æ·ÑÇÖÞ×ۺϾþÃÖÐÎÄ×ÖÄ»| ÑÇÖÞ¾«Æ·¹ú²úÃâ·Ñ| ÑÇÖÞ×ÛºÏÒ»Çø¶þÇøÈýÇøËÄÇøÎåÇø| ³ÉÄêÍøÔÚÏß¹Û¿´Ãâ·Ñ¹Û¿´ÍøÖ·|