<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>聚沙成塔-小哈的记事薄 &#187; memory</title>
	<atom:link href="http://www.hashei.me/tag/memory/feed" rel="self" type="application/rss+xml" />
	<link>http://www.hashei.me</link>
	<description>一个系统工程师的絮叨</description>
	<lastBuildDate>Tue, 10 Jan 2012 18:03:42 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		
<!-- Start Of Script Generated By WP-PostViews Plus -->
<script type='text/javascript' src='http://hashei.me/wp-includes/js/jquery/jquery.js?ver=1.3.2'></script>
<script type="text/javascript">
/* <![CDATA[ */
jQuery.ajax({type:'GET',url:'http://hashei.me/wp-content/plugins/wp-postviews-plus/postviews_plus.php',data:'todowppvp=add&type=tag&id=161_1',cache:false,dataType:'script'});
/* ]]> */
</script>
<!-- End Of Script Generated By WP-PostViews Plus -->
	<item>
		<title>Investigating Out of Memory/Memory Leak Problems</title>
		<link>http://www.hashei.me/2009/09/investigating_out_of_memory_and_memory_leak_problems.html?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=investigating_out_of_memory_and_memory_leak_problems</link>
		<comments>http://www.hashei.me/2009/09/investigating_out_of_memory_and_memory_leak_problems.html#comments</comments>
		<pubDate>Tue, 22 Sep 2009 07:46:00 +0000</pubDate>
		<dc:creator>hashei</dc:creator>
				<category><![CDATA[Websphere系列]]></category>
		<category><![CDATA[weblogic]]></category>
		<category><![CDATA[性能优化]]></category>
		<category><![CDATA[heap]]></category>
		<category><![CDATA[memory]]></category>
		<category><![CDATA[Memory Leak]]></category>
		<category><![CDATA[OutOfMemory]]></category>

		<guid isPermaLink="false">http://www.hashei.me/2009/09/investigating_out_of_memory_and_memory_leak_problems.html</guid>
		<description><![CDATA[本文原文地址为http://support.bea.com/support_news/product_troubleshooting/Investigating_Out_of_Memory_Memory_Leak_Pattern.html
但现在这个网址已经无法访问，我在Metalink找到这篇文章并与大家分享。文章发表的较早，但是OOM发生的原理和解决的方法不变。文中提到的/3GB参数和垃圾回收日志分析的方法我在《JAVA性能优化—IBM JDK JVM参数设置》和《JAVA性能优化-GC日志分析》都提到过。如果英文的看起来比较麻烦，我google到台湾人做的一份翻译JavaAPsvr_A_200411_MemoryLeak，不过我看着“记忆体”觉得更别扭。
Problem Description
Out Of Memory (OOM) &#8211; An application displays Out of Memory errors due to memory exhaustion, either in java heap or native memory.
Memory Leak &#8211; Constant memory growth in either java heap or native memory, which will eventually end up in out of memory situation. The techniques to debug the memory leak [...]]]></description>
			<content:encoded><![CDATA[<p><span style="font-weight: normal;">本文原文地址为<a href="http://support.bea.com/support_news/product_troubleshooting/Investigating_Out_of_Memory_Memory_Leak_Pattern.html">http://support.bea.com/support_news/product_troubleshooting/Investigating_Out_of_Memory_Memory_Leak_Pattern.html</a></span></p>
<p><span style="font-weight: normal;"><a href="http://support.bea.com/support_news/product_troubleshooting/Investigating_Out_of_Memory_Memory_Leak_Pattern.html"></a>但现在这个网址已经无法访问，我在Metalink找到这篇文章并与大家分享。文章发表的较早，但是OOM发生的原理和解决的方法不变。文中提到的/3GB参数和垃圾回收日志分析的方法我在<a title="IBM JDK优化" href="http://www.hashei.me/2009/05/tuning-the-ibm-jdk.html" target="_blank">《JAVA性能优化—IBM JDK JVM参数设置</a>》和<a title="GC日志分析" href="http://www.hashei.me/2009/06/analyse-the-gc-logs.html" target="_blank">《JAVA性能优化-GC日志分析》</a>都提到过。如果英文的看起来比较麻烦，我google到台湾人做的一份翻译<a href="http://hashei.me/wp-content/uploads/2009/09/JavaAPsvr_A_200411_MemoryLeak.pdf">JavaAPsvr_A_200411_MemoryLeak</a>，不过我看着“记忆体”觉得更别扭。</span></p>
<h3>Problem Description</h3>
<p><strong>Out Of Memory</strong> (OOM) &#8211; An application displays Out of Memory errors due to memory exhaustion, either in java heap or native memory.</p>
<p><strong>Memory Leak</strong> &#8211; Constant memory growth in either java heap or native memory, which will eventually end up in out of memory situation. The techniques to debug the memory leak situations are the same as the out of memory situations.</p>
<h3>Problem Troubleshooting</h3>
<p>Please note that not all of the following items would need to be done. Some issues can be solved by only following a few of the items.</p>
<h3>Quick Links:</h3>
<ul>
<li><a href="#Java">Java heap, Native memory, Process size</a></li>
<li><a href="#Difference">Difference between process address space and physical memory</a></li>
<li><a href="#Why">Why does the OOM problem occur and What does the JVM do in this situation?</a></li>
<li><a href="#Steps">Steps to debug the problem</a>
<ul>
<li><a href="#determine_OOM_type">Determine if Java OOM or Native OOM</a></li>
<li><a href="#Java_OOM">Java OOM</a></li>
<li><a href="#Native_OOM">Native OOM</a></li>
</ul>
</li>
<li><a href="#HP">HP JVM specific tools/tips</a>&gt;</li>
<li><a href="#Jrockit">Jrockit specific features</a></li>
<li><a href="#Bibliography">Bibliography</a></li>
</ul>
<h3><a name="Java"></a></h3>
<p><strong>Java heap</strong> This is the memory that the JVM uses to allocate java objects. The maximum value of java heap memory is specified using <code>�Xmx</code> flag in the java command line. If the maximum heap size is not specified, then the limit is decided by the JVM considering factors like the amount of physical memory in the machine and the amount of free memory available at that moment. It is always recommended to specify the max java heap value.</p>
<p><strong>Native memory</strong> This is the memory that the JVM uses for its own internal operations. The amount of native memory heap that will be used by the JVM depends on the amount of code generated, threads created, memory used during GC for keeping java object information and temporary space used during code generation, optimization etc.</p>
<p>If there is a third party native module, it could also use the native memory. For example, native JDBC drivers allocate native memory.</p>
<p>The max amount of native memory is limited by the virtual process size limitation on any given OS and the amount of memory already committed for the java heap with -<code>Xmx</code> flag. For example, if the application can allocate a total of 3 GB and if the max java heap is 1 GB, then the max possible native memory is approximately 2 GB.</p>
<p><strong>Process size</strong> Process size will be the sum of the java heap, native memory and the memory occupied by the loaded executables and libraries. On 32 bit operating systems, the virtual address space of a process can go up to 4 GB. Out of this 4 GB, the OS kernel reserves some part for itself (typically 1 ~ 2 GB). The remaining is available for the application.</p>
<p>Windows ：By default, 2 GB is available for the application and 2 GB is reserved for Kernel&#8217;s use. However, on some variants of Windows, there is a /3GB switch which can be used to change this ratio such that the application gets 3 GB. More details on the /3GB switch can be found at:</p>
<p><a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/memory/base/4gt_ram_tuning.asp">http://msdn.microsoft.com/library/default.asp?url=/library/en-us/memory/base/4gt_ram_tuning.asp</a></p>
<p>RH Linux AS 2.1 ： 3 GB is available for the application.</p>
<p>For other operating systems, please refer to the OS documentation for your configuration.</p>
<p><a href="http://www.hashei.me/TEMP/non1536.htm#TOP">Top of Page</a></p>
<p><span id="more-696"></span></p>
<h3><a name="Difference"></a></h3>
<p>Each process gets its own address space. In 32 bit operating systems, this address space will range from 0 to 4 GB. This is independent of the available RAM or swap space in the machine. The total physical memory available on the machine is the sum of RAM and the swap space available on that machine. All the running processes share this physical memory.</p>
<p>The memory address within a process is virtual. The kernel maps this virtual address to the physical address. The physical address points to a location somewhere in the physical memory. At any given time, the sum of all the virtual memory used by the running processes in a machine cannot exceed the total physical memory available on that machine.</p>
<p><a href="http://www.hashei.me/TEMP/non1536.htm#TOP">Top of Page</a></p>
<h3><a name="Why"></a></h3>
<h4>Out of memory in java heap</h4>
<p>The JVM throws java out of memory (java OOM) error if it is not able get more memory in java heap to allocate more java objects. The JVM cannot allocate more java objects if the java heap is full of live objects and it is not able to expand the java heap anymore.</p>
<p>In this situation, the JVM lets the application decide on what to do after throwing the java.lang.OutOfMemoryError. For example, the application may handle this error and decide to shut down itself in a safe way or decide to run ignoring this error. If the application doesn&#8217;t handle this error, then the thread that throws this error will exit (you will not see this thread if you take a java thread dump).</p>
<p>In case of weblogic server, this error is handled if it is thrown by an execute thread and the error is logged. If this error is being thrown continuously, then the core health monitor thread shuts down the weblogic server.</p>
<h4>Out of memory in native heap</h4>
<p>The JVM throws native out of memory (native OOM) if it is not able to get any more native memory. This usually happens when the process reaches the process size limitation on that OS or the machine runs out of RAM and swap space.</p>
<p>When this happens, the JVM handles the native OOM condition, logs a message saying that it ran out of native memory or unable to acquire memory and exits. If the JVM or any other loaded module (like libc or a third party module) doesn&#8217;t handle this native OOM situation, then the OS will send a sigabort signal to the JVM which will make the JVM exit. Usually, the JVMs will generate a core file when it gets a sigabort signal.</p>
<p><a href="http://www.hashei.me/TEMP/non1536.htm#TOP">Top of Page</a></p>
<h3><a name="Steps"></a></h3>
<h4><a name="determine_OOM_type"></a>Determine whether it is a Java OOM or Native OOM</h4>
<ul>
<li>If the stdout/stderr message says that this is a java.lang.OutOfMemoryError, then this is Java OOM</li>
<li>If the stdout/stderr message says that it failed to acquire memory, then this is a Native OOM</li>
</ul>
<p>Please note that the above messages goes to stdout or stderr and not to the application specific log files like weblogic.log</p>
<p><a href="http://www.hashei.me/TEMP/non1536.htm#TOP">Top of Page</a></p>
<h4><a name="Java_OOM"></a>For Java OOM:</h4>
<ol>
<li><strong>Collect and analyze the verbose gc output</strong>
<ol>
<li><strong>Add &#8220;<code>-verbosegc" </code> flag in the java command line</strong>. This will print GC activity info to stdout/stderr. Redirect the stdout/stderr to a file. Run the application until the problem gets reproduced.</li>
<li><strong>Make sure that the JVM does the following before throwing java OOM</strong><strong>Full GC run:</strong>Does a full GC and all the un-reachable, phantomly, weakly and softly reachable objects are removed and those spaces are reclaimed. More details on different levels of object reachability can be found at:<a href="http://java.sun.com/developer/technicalArticles/ALT/RefObj">http://java.sun.com/developer/technicalArticles/ALT/RefObj</a>
<p>You can check whether full GC was done before the OOM message. A message like the following is printed when a full GC is done (format varies depending on the JVM , Check JVM help message to understand the format)</p>
<p>[memory ] 7.160: GC 131072K-&gt;130052K (131072K) in 1057.359 ms</p>
<p>The format of the above output follows (Note: the same format will be used throughout this Pattern):</p>
<p>[memory ] &lt;start&gt;: GC &lt;before&gt;K-&gt;&lt;after&gt;K (&lt;heap&gt;K), &lt;total&gt; ms<br />
[memory ] &lt;start&gt; &#8211; start time of collection (seconds since jvm start)<br />
[memory ] &lt;before&gt; &#8211; memory used by objects before collection (KB)<br />
[memory ] &lt;after&gt; &#8211; memory used by objects after collection (KB)<br />
[memory ] &lt;heap&gt; &#8211; size of heap after collection (KB)<br />
[memory ] &lt;total&gt; &#8211; total time of collection (milliseconds)</p>
<p>However, there is no way to conclude whether the soft/weak/phantomly reachable objects are removed using the verbose messages. If you suspect that these objects are still around when OOM was thrown, contact the JVM vendor.</p>
<p>If the garbage collection algorithm is a generational algorithm (gencopy or gencon in case of Jrockit and the default algorithm in case of other JDKs), you will also see verbose output something like this:</p>
<p>[memory ] 2.414: Nursery GC 31000K-&gt;20760K (75776K), 0.469 ms</p>
<p>The above is the nursery GC (or young GC) cycle which will promote live objects from nursery (or young space) to old space. This cycle is not important for our analysis. More details on generational algorithms can be found in JVM documentation.</p>
<p>If the GC cycle doesn&#8217;t happen before java OOM, then it is a JVM bug.</p>
<p><strong>Full compaction:</strong></p>
<p>Make sure that the JVM does proper compaction work and the memory is not fragmented which could prevent large objects being allocated and trigger a java OOM error.</p>
<p>Java objects need the memory to be contiguous. If the available free memory is fragmented, then the JVM will not be able to allocate a large object, as it may not fit in any of the available free chunks. In this case, the JVM should do a full compaction so that more contiguous free memory can be formed to accommodate large objects.</p>
<p>Compaction work involves moving of objects (data) from one place to another in the java heap memory and updating the references to those objects to point to the new location. JVMs may not compact all the objects unless if there is a need. This is to reduce the pause time of GC cycle.</p>
<p>We can check whether the java OOM is due to fragmentation by analyzing the verbose gc messages. If you see output similar to the following where the OOM is being thrown even whether there is free java heap available, then it is due to fragmentation.</p>
<p>[memory ] 8.162: GC 73043K-&gt;72989K (131072K) in 12.938 ms<br />
[memory ] 8.172: GC 72989K-&gt;72905K (131072K) in 12.000 ms<br />
[memory ] 8.182: GC 72905K-&gt;72580K (131072K) in 13.509 ms<br />
java.lang.OutOfMemoryError</p>
<p>In the above case you can see that the max heap specified was 128MB and the JVM threw OOM when the actual memory usage is only 72580K. The heap usage is only 55%. Therefore, the effect of fragmentation in this case is to throw OOM even when there is 45% of free heap. This is a JVM bug or limitation.You should contact the JVM vendor.</li>
</ol>
</li>
<li><strong>If the JVM does its work properly</strong> (all the things mentioned in the above step), then the java OOM could be an application issue. The application might be leaking some java memory constantly, which may cause this problem. Or, the application uses more live objects and it needs more java heap memory. The following things can be checked in the application:
<ul>
<li><strong>Caching in the application</strong> &#8211; If the application caches java objects in memory, then we should make sure that this cache is not growing constantly. There should be a limit for the number of objects in the cache. We can try reducing this limit to see if it reduces the java heap usage.Java soft references can also be used for data caching as softly reachable objects are guaranteed to be removed when the JVM runs out of java heap.</li>
<li><strong>Long living objects</strong> &#8211; If there are long living objects in the application, then we can try reducing the life of the objects if possible. For example, tuning HTTP session timeout will help in reclaiming the idle session objects faster.</li>
<li><strong>Memory leaks</strong> : One example of memory leak is when using database connection pools in application server. When using connection pools, the JDBC statement and resultset objects must be explicitly closed in a finally block. This is due to the fact that calling close() on the connection objects from pool will simply return the connection back to the pool for re-use and it doesn&#8217;t actually close the connection and the associated statement/resultset objects.It is recommended to follow the coding practices suggested in the following documents to avoid memory leaks in your application.JDBC &#8211; <a href="http://e-docs.bea.com/wls/docs81/jdbc/troubleshooting.html#1026696">http://e-docs.bea.com/wls/docs81/jdbc/troubleshooting.html#1026696</a>JNDI &#8211; <a href="http://e-docs.bea.com/wls/docs81/jndi/jndi.html#472853">http://e-docs.bea.com/wls/docs81/jndi/jndi.html#472853</a>
<p>JMS &#8211; <a href="http://e-docs.bea.com/wls/docs81/jms/implement.html#1194127">http://e-docs.bea.com/wls/docs81/jms/implement.html#1194127</a></li>
<li><strong>Increase the java heap</strong> &#8211; We can also try increasing the java heap if possible to see whether that solves the problem.</li>
<li>Workaround &#8211; As a temporary work around, the application may be gracefully re-started when the java heap usage goes about 90%. When following this work around, the java max heap can be set to as high as possible so that the application will take more time to fill all the java heap. The java heap usage can be monitored by adding &#8216;-verbosegc&#8217; flag in the java command line which will send the GC/ heap usage info to stdout or stderr.</li>
</ul>
</li>
<li><strong>If none of the above suggestion is applicable to the application</strong>, then we need to use a JVMPI (JVM Profiler Interface) based profiler like Jprobe or OptimizeIt to find out which objects are occupying the java heap. The profilers also give details on the place in the java code from where these objects are being created. This document doesn&#8217;t cover the details on each profiler. The profiler documentation can be referred to understand how to set and start the application with this profilers. In general, JVMPI based profilers have high overhead and drastically reduce the performance of the application. Therefore, it is not advisable to use these profilers in production environments.<a href="http://www.borland.com/optimizeit">http://www.borland.com/optimizeit</a><a href="http://www.quest.com/jprobe">http://www.quest.com/jprobe</a></li>
</ol>
<p><a href="http://www.hashei.me/TEMP/non1536.htm#TOP">Top of Page</a></p>
<h4><a name="Native_OOM"></a>For Native OOM Problem</h4>
<ol>
<li><strong>Collect the following information:</strong>
<ol>
<li><code><strong>�verbosegc</strong></code> output to monitor the java heap usage. This will help to understand the java memory requirement for this application.It should be noted that independent of the actual java heap usage by the application, the amount of max heap specified (using <code>�Xmx</code> flag in the java command line) is reserved at the JVM startup and this reserved memory is not available for any other purpose.In case of Jrockit, use <code>-verbose</code> instead of <code>-verbosegc</code> as this gives codegen information in addition to GC information.</li>
<li><strong>Record the process virtual memory size</strong> periodically from the time the application was started until the JVM runs out of native memory. This will help to understand whether the process really hits the size limitation on that OS.In case of Windows, use the following procedure to monitor the virtual process size:
<ol>
<li>
<ol>
<li>In the Start -&gt; Run\dialog, enter &#8220;perfmon&#8221; and click OK.</li>
<li>In the &#8220;Performance&#8221; window that pops up, click on the &#8220;+&#8221; button (above the graph).</li>
<li>Select the following options in the resulting dialog:
<ul>
<li>Performance object: Process (not the default Processor)</li>
<li>Select counter from list: Virtual Bytes</li>
<li>Select instances from list: Select the JVM (java) instance</li>
<li>Click &#8220;Add&#8221;, then &#8220;Close&#8221;</li>
</ul>
</li>
</ol>
</li>
<p>In case of Unix or Linux, for a given PID, the virtual memory size can be found using this command : <code>ps -p &lt;PID&gt; -o vsz</code>.</p>
<p>In case of Linux, each java thread within a single JVM instance is shown as a separate process. It is enough if we take the PID of the root java process. The root java process can be found using the <code>�forest</code> option for<code>ps</code> command. For example, <code>ps �lU &lt;user&gt; --forest</code> will give a ASCII tree art for all the processes started by the specified user. You can find the root java from the tree art.</ol>
</li>
</ol>
</li>
<li><strong>Memory availability in the machine</strong>If the machine doesn&#8217;t have enough RAM and swap space, then the OS will not be able to give more memory to this process that could also result in out of memory. Make sure that the sum of RAM and swap space in the disk is sufficient to cater to all the running processes in that machine.</li>
<li><strong>Tuning java heap</strong>If the java heap usage is well within the max heap, then reducing the java max heap will give more native memory to the JVM. This is not a solution but a workaround that can be tried. Since the OS limits the process size, we need to strike a balance between the java heap and the native heap.</li>
<li><strong>Native memory usage by the JVM</strong>The amount of native memory usage by the JVM is expected to flatten out after all the classes are loaded and the methods have been called (code generation is over). This usually happens within the first few hours for most of the applications. After that, the JVM uses only little native memory that may be due to run time class loading, code generation due to optimization etc.In order to narrow down the problem, try disabling run time optimizations and check whether that makes any difference.
<ul>
<li>In case of Jrockit, <code>-Xnoopt</code> flag can be used to disable run time optimizations.</li>
<li>In case of SUN hotspot JVM, <code>-Xint</code> flag will force the JVM to run in interpreted mode (no code generation).</li>
</ul>
<p>If the native memory usage continues to grow constantly throughout the run, then this could be a memory leak in the native code.</li>
<li><strong>Third party native modules or JNI code in the application</strong>Check whether you are using any third party native module like database drivers. These native modules could also allocate native memory and the leak may be from these modules. In order to narrow down the problem, you should attempt to reproduce the problem without these third party modules. For example, you can use pure java drivers instead of native database drivers.Check whether your application uses some JNI code. This could also be causing native memory leak and you can try to run the application without the JNI code if possible.</li>
<li><strong>If the source of native memory cannot be found after the above steps</strong>, then you need to work with the JVM vendor to get a special build which can trace the native memory allocation calls and give more information about the leak.</li>
</ol>
<p><a href="http://www.hashei.me/TEMP/non1536.htm#TOP">Top of Page</a></p>
<h3><a name="HP"></a></h3>
<p>The following URL gives some tools and tips specific to OOM situations with HP JVM: <a href="http://www.hp.com/products1/unix/java/infolibrary/prog_guide/diag_memory_leaks.html">HP JVM tools/tips</a></p>
<h3><a name="Jrockit"></a></h3>
<p>Jrockit 8.1 SP1 and above supports JRA recording (Java Runtime Analyzer). This is useful to gather information at JVM run time which will give information about the application like, number of GCs running, number of soft/weak/phantom references, hot methods etc. It is useful to make a recording for few minutes and analyze the data if the JVM has performance problems or hang problems. More details on this can be found in Jrockit docs.</p>
<p><a href="http://edocs.bea.com/wljrockit/docs142/usingJRA/jra.html">http://edocs.bea.com/wljrockit/docs142/usingJRA/jra.html</a></p>
<h3><a name="Bibliography"></a></h3>
<ul>
<li><a href="http://java.sun.com/">Sun Java Web Site</a></li>
<li><a href="http://forum.java.sun.com/">Sun Java Newsgroups</a></li>
<li><a href="http://edocs.bea.com/wljrockit/docs81/index.html">JRockit Documentation</a></li>
<li><a href="http://dev2dev.bea.com/products/wljrockit81/index.jsp">dev2dev (JRockit)</a></li>
<li><a href="news://newsgroups.bea.com/jrockit.developer.interest.general">JRockit newsgroup</a></li>
</ul>
<hr /><small>  Copyright &copy; 2008 This feed is for personal, non-commercial use only<br />
<a href=www.hashei.com >聚沙成塔-小哈的记事薄</a> by hashei 
如果喜欢，欢迎订阅<a href=feed.hashei.com >feed.hashei.com</a><br />
Digital Fingerprint:
 10f920a9f2bae51c3c73c4f5fb50a949</small>]]></content:encoded>
			<wfw:commentRss>http://www.hashei.me/2009/09/investigating_out_of_memory_and_memory_leak_problems.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Linux System and Performance Monitoring(Memory篇)</title>
		<link>http://www.hashei.me/2009/09/linux_system_and_performance_monitoring_memory.html?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=linux_system_and_performance_monitoring_memory</link>
		<comments>http://www.hashei.me/2009/09/linux_system_and_performance_monitoring_memory.html#comments</comments>
		<pubDate>Wed, 09 Sep 2009 06:22:00 +0000</pubDate>
		<dc:creator>hashei</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[性能优化]]></category>
		<category><![CDATA[memory]]></category>
		<category><![CDATA[paging]]></category>
		<category><![CDATA[swap space]]></category>
		<category><![CDATA[性能监控]]></category>

		<guid isPermaLink="false">http://www.hashei.me/2009/09/linux_system_and_performance_monitoring_memory.html</guid>
		<description><![CDATA[作者:tonnyom   原载: http://www.sanotes.net/html/y2009/376.html    版权所有。转载时必须以链接形式注明作者和原始出处及本声明。
Linux System and Performance Monitoring(Memory篇)   Date: 2009.07.21    Author: Darren Hoch    译: Tonnyom[AT]hotmail.com
5.0 Virtual Memory介绍
虚拟内存就是采用硬盘对物理内存进行扩展,所以对可用内存的增加是要相对在一个有效范围内的.内核会写当前未使用内存块的内容到硬盘上,此时这部分内存被用于其它用途.当再一次需要原始内容时,此时再读回到内存中.这对于用户来说,是完全透明的;在Linux 下运行的程序能够看到,也仅仅是大量的可用内存,同时也不会留意到,偶尔还有部分是驻留在磁盘上的.当然,在硬盘上进行读和写,都是很慢的(大约会慢上千倍),相对于使用真实内存的话,因此程序无法运行的更快.用硬盘的一部分作为Virtual Memory,这就被称为”swap space”(译注:交换空间).
5.1 Virtual Memory Pages
虚拟内存被分为很多 pages(译注:页),在X86架构中,每个虚拟内存页为 4KB.当内核写内存到磁盘或者读磁盘到内存,这就是一次写内存到页的过程.内核通常是在swap 分区和文件系统之间进行这样的操作.
5.2 Kernel Memory Paging
内存分页在正常情况下总是活跃的,与memory swapping(译注:内存交换)之间不要搞错了.内存分页是指内核会定期将内存中的数据同步到硬盘,这个过程就是Memory Paging.日复一日,应用最终将会消耗掉所有的内存空间.考虑到这点,内核就必须经常扫描内存空间并且收回其中未被使用的内存页,然后再重新分配内存空间给其他应用使用.
5.3 The Page Frame Reclaim Algorithm(PFRA)(译注:页框回收算法)
PFRA 就是OS 内核用来回收并释放内存空间的算法.PFRA 选择哪个内存页被释放是基于内存页类型的.页类型有以下几种:
Unreclaimable –锁定的，内核保留的页面   [...]]]></description>
			<content:encoded><![CDATA[<p>作者:tonnyom   <br />原载: <a href="http://www.sanotes.net/html/y2009/376.html">http://www.sanotes.net/html/y2009/376.html</a>    <br />版权所有。转载时必须以链接形式注明作者和原始出处及本声明。</p>
<p>Linux System and Performance Monitoring(Memory篇)   <br />Date: 2009.07.21    <br />Author: Darren Hoch    <br />译: Tonnyom[AT]hotmail.com</p>
<p>5.0 Virtual Memory介绍</p>
<p>虚拟内存就是采用硬盘对物理内存进行扩展,所以对可用内存的增加是要相对在一个有效范围内的.内核会写当前未使用内存块的内容到硬盘上,此时这部分内存被用于其它用途.当再一次需要原始内容时,此时再读回到内存中.这对于用户来说,是完全透明的;在Linux 下运行的程序能够看到,也仅仅是大量的可用内存,同时也不会留意到,偶尔还有部分是驻留在磁盘上的.当然,在硬盘上进行读和写,都是很慢的(大约会慢上千倍),相对于使用真实内存的话,因此程序无法运行的更快.用硬盘的一部分作为Virtual Memory,这就被称为”swap space”(译注:交换空间).</p>
<p>5.1 Virtual Memory Pages</p>
<p>虚拟内存被分为很多 pages(译注:页),在X86架构中,每个虚拟内存页为 4KB.当内核写内存到磁盘或者读磁盘到内存,这就是一次写内存到页的过程.内核通常是在swap 分区和文件系统之间进行这样的操作.</p>
<p>5.2 Kernel Memory Paging</p>
<p>内存分页在正常情况下总是活跃的,与memory swapping(译注:内存交换)之间不要搞错了.内存分页是指内核会定期将内存中的数据同步到硬盘,这个过程就是Memory Paging.日复一日,应用最终将会消耗掉所有的内存空间.考虑到这点,内核就必须经常扫描内存空间并且收回其中未被使用的内存页,然后再重新分配内存空间给其他应用使用.</p>
<p>5.3 The Page Frame Reclaim Algorithm(PFRA)(译注:页框回收算法)</p>
<p>PFRA 就是OS 内核用来回收并释放内存空间的算法.PFRA 选择哪个内存页被释放是基于内存页类型的.页类型有以下几种:</p>
<p>Unreclaimable –锁定的，内核保留的页面   <br />Swappable –匿名的内存页    <br />Syncable –通过硬盘文件备份的内存页    <br />Discardable –静态页和被丢弃的页</p>
<p>除了第一种（Unreclaimable）之外其余的都可以被PFRA进行回收.</p>
<p>与PFRA 相关的,还包括kswapd 内核线程以及Low On Memory Reclaiming(LMR算法) 这2种进程和实现.</p>
<p>5.4 kswapd</p>
<p>kswapd 进程负责确保内存空间总是在被释放中.它监控内核中的pages_high和pages_low阀值.如果空闲内存的数值低于 pages_low,则每次 kswapd 进程启动扫描并尝试释放32个free pages.并一直重复这个过程,直到空闲内存的数值高于 pages_high.</p>
<p>kswapd 进程完成以下几个操作:</p>
<p>1,如果该页处于未修改状态,则将该页放置回空闲列表中.   <br />2,如果该页处于已修改状态并可备份回文件系统,则将页内容写入到磁盘.    <br />3,如果该页处于已修改状态但没有任何磁盘备份,则将页内容写入到swap device.</p>
<p># ps -ef | grep kswapd   <br />root 30 1 0 23:01 ? 00:00:00 [kswapd0]</p>
<p>5.5 Kernel Paging with pdflush</p>
<p>pdflush 进程负责将内存中的内容和文件系统进行同步操作.也就是说,当一个文件在内存中进行修改后, pdflush 将负责写回到磁盘上.</p>
<p># ps -ef | grep pdflush   <br />root 28 3 0 23:01 ? 00:00:00 [pdflush]    <br />root 29 3 0 23:01 ? 00:00:00 [pdflush]</p>
<p>当内存中存在10% 的脏页,pdflush 将被启动同步脏页回文件系统里.这个参数值可以通过 vm.dirty_background_ratio 来进行调整.</p>
<p>(译注:   <br />Q:什么是脏页?    <br />A:由于内存中页缓存的缓存作用,写操作实际上都是延迟的.当页缓存中的数据比磁盘存储的数据还要更新时,那么该数据就被称做脏页.)</p>
<p># sysctl -n vm.dirty_background_ratio   <br />10</p>
<p>在多数环境下,Pdflush与PFRA是独立运行的,当内核调用LMR时,LMR 就触发pdflush将脏页写入到磁盘里.</p>
<p>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++   <br />在2.4 内核下,一个高负荷的内存环境中,系统将遇到交换过程中不断的崩溃.这是因为PFRA 从一个运行进程中,偷取其中一个内存页并尝试使用.导致结果就是,这个进程如果要回收那个页时,要是没有就会尝试再去偷取这个页,这样一来,就越来越糟糕了.在2.6 内核下,使用”Swap token”修复了这个BUG,用来防止PFRA 不断从一个进程获取同一个页.    <br />++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++</p>
<p>5.6 案例学习:大量的入口I/O</p>
<p>vmstat 工具报告里除了CPU 使用情况,还包括了虚拟内存.以下就是vmstat 输出中关于虚拟内存的部分:</p>
<p>Table 2: The vmstat Memory Statistics   <br />Field Description    <br />Swapd The amount of virtual memory in KB currently in use. As free memory reaches low thresholds, more data is paged to the swap device.    <br />当前虚拟内存使用的总额(单位:KB).空闲内存达到最低的阀值时,更多的数据被转换成页到交换设备中.    <br />Free The amount of physical RAM in kilobytes currently available to running applications.    <br />当前内存中可用空间字节数.    <br />Buff The amount of physical memory in kilobytes in the buffer cache as a result of read() and write() operations.    <br />当前内存中用于read()和write()操作的缓冲区中缓存字节数    <br />Cache The amount of physical memory in kilobytes mapped into process address space.    <br />当前内存中映射到进程地址空间字节数    <br />So The amount of data in kilobytes written to the swap disk.    <br />写入交换空间的字节数总额    <br />Si The amount of data in kilobytes written from the swap disk back into RAM.    <br />从交换空间写回内存的字节数总额    <br />Bo The amount of disk blocks paged out from the RAM to the filesystem or swap device.    <br />磁盘块页面从内存到文件或交换设备的总额    <br />Bi The amount of disk blocks paged into RAM from the filesystem or swap device.    <br />磁盘块页面从文件或交换设备到内存的总额</p>
<p>以下 vmstat 的输出结果,就是演示一个在I/O 应用中,虚拟内存在高负荷情况下的环境</p>
<p># vmstat 3   <br />procs memory swap io system cpu    <br />r b swpd free buff cache si so bi bo in cs us sy id wa    <br />3 2 809192 261556 79760 886880 416 0 8244 751 426 863 17 3 6 75    <br />0 3 809188 194916 79820 952900 307 0 21745 1005 1189 2590 34 6 12 48    <br />0 3 809188 162212 79840 988920 95 0 12107 0 1801 2633 2 2 3 94    <br />1 3 809268 88756 79924 1061424 260 28 18377 113 1142 1694 3 5 3 88    <br />1 2 826284 17608 71240 1144180 100 6140 25839 16380 1528 1179 19 9 12 61    <br />2 1 854780 17688 34140 1208980 1 9535 25557 30967 1764 2238 43 13 16 28    <br />0 8 867528 17588 32332 1226392 31 4384 16524 27808 1490 1634 41 10 7 43    <br />4 2 877372 17596 32372 1227532 213 3281 10912 3337 678 932 33 7 3 57    <br />1 2 885980 17800 32408 1239160 204 2892 12347 12681 1033 982 40 12 2 46    <br />5 2 900472 17980 32440 1253884 24 4851 17521 4856 934 1730 48 12 13 26    <br />1 1 904404 17620 32492 1258928 15 1316 7647 15804 919 978 49 9 17 25    <br />4 1 911192 17944 32540 1266724 37 2263 12907 3547 834 1421 47 14 20 20    <br />1 1 919292 17876 31824 1275832 1 2745 16327 2747 617 1421 52 11 23 14    <br />5 0 925216 17812 25008 1289320 12 1975 12760 3181 772 1254 50 10 21 19    <br />0 5 932860 17736 21760 1300280 8 2556 15469 3873 825 1258 49 13 24 15</p>
<p>根据观察值,我们可以得到以下结论:</p>
<p>1,大量的disk pages(bi)被写入内存,很明显在进程地址空间里,数据缓存(cache)也在不断的增长.</p>
<p>2,在这个时间点上,空闲内存(free) 始终保持在17MB,即使数据从硬盘读入而在消耗RAM.</p>
<p>3,为了维护空闲列表, kswapd 从读/写缓存区(buff)中获取内存并分配到空闲列表里.很明显可以看到buffer cache(buff) 在逐渐的减少中.</p>
<p>4, 同时kswapd 进程不断的写脏页到swap device(so)时,很明显虚拟内存的利用率是在逐渐的增加中(swpd).</p>
<p>5.7 结论</p>
<p>监控虚拟内存性能由以下几个部分组成:</p>
<p>1,当系统中出现较少的页错误,获得最好的响应时间,是因为memory caches(译注:内存高速缓存)比disk caches更快(译注:磁盘高速缓存).</p>
<p>2,较少的空闲内存,是件好事情,那意味着缓存的使用更有效率.除非在不断的写入swap device和disk.</p>
<p>3,如果系统不断报告,swap device总是繁忙中,那就意味着内存已经不足,需要升级了.</p>
<hr /><small>  Copyright &copy; 2008 This feed is for personal, non-commercial use only<br />
<a href=www.hashei.com >聚沙成塔-小哈的记事薄</a> by hashei 
如果喜欢，欢迎订阅<a href=feed.hashei.com >feed.hashei.com</a><br />
Digital Fingerprint:
 10f920a9f2bae51c3c73c4f5fb50a949</small>]]></content:encoded>
			<wfw:commentRss>http://www.hashei.me/2009/09/linux_system_and_performance_monitoring_memory.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

