<?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://blog.zhourunsheng.com/tag/memory/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.zhourunsheng.com</link>
	<description>天空一朵雨做的云</description>
	<lastBuildDate>Sat, 08 May 2021 05:17:21 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.41</generator>
	<item>
		<title>Java开发内存优化导读</title>
		<link>http://blog.zhourunsheng.com/2013/08/java%e5%bc%80%e5%8f%91%e5%86%85%e5%ad%98%e4%bc%98%e5%8c%96%e5%af%bc%e8%af%bb/</link>
		<comments>http://blog.zhourunsheng.com/2013/08/java%e5%bc%80%e5%8f%91%e5%86%85%e5%ad%98%e4%bc%98%e5%8c%96%e5%af%bc%e8%af%bb/#comments</comments>
		<pubDate>Tue, 13 Aug 2013 02:32:05 +0000</pubDate>
		<dc:creator><![CDATA[润物无声]]></dc:creator>
				<category><![CDATA[程序设计]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Memory]]></category>

		<guid isPermaLink="false">http://blog.zhourunsheng.com/?p=1752</guid>
		<description><![CDATA[<p>在开发Java的过程中，怎么样合理的利用Object，资源的申请与释放，每种类型的Object占用的内存大小是 [&#8230;]</p>
<p><a rel="nofollow" href="http://blog.zhourunsheng.com/2013/08/java%e5%bc%80%e5%8f%91%e5%86%85%e5%ad%98%e4%bc%98%e5%8c%96%e5%af%bc%e8%af%bb/">Java开发内存优化导读</a>，首发于<a rel="nofollow" href="http://blog.zhourunsheng.com">润物无声</a>。</p>
]]></description>
				<content:encoded><![CDATA[<p>在开发Java的过程中，怎么样合理的利用<strong>Object</strong>，资源的申请与释放，每种类型的<strong>Object</strong>占用的内存大小是多少，有没有可以替换的lib可以使用。鉴于效率的考量和内存占用的考量，我们应该选择什么样的数据结构，那么如下的文章将会找到答案。</p>
<p>This article will give you the general advices on memory consumption optimization in Java.</p>
<p>Memory usage optimization is the most important type of optimization in Java. <a href="http://www.amazon.com/gp/product/0123797519/ref=as_li_ss_tl?ie=UTF8&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0123797519&amp;linkCode=as2&amp;tag=javaperfor07e-20" rel="nofollow">Current systems are limited by memory access times rather than by CPU frequency</a><img alt="" src="http://www.assoc-amazon.com/e/ir?t=javaperfor07e-20&amp;l=as2&amp;o=1&amp;a=0123797519" width="1" height="1" border="0" /> (otherwise, why CPU producers are implementing all these L1s, L2s and L3s?). It means that by reducing your application memory footprint you will most likely improve your program data processing speed by making your CPU to wait for smaller amount of data. Now let’s get back to Java.<span id="more-1752"></span></p>
<h2>General Java memory layout information</h2>
<p>First of all, we have to <a href="http://java-performance.info/memory-introspection-using-sun-misc-unsafe-and-reflection/">revise the memory layout of Java objects</a>: any Java <strong>Object</strong> occupies at least 16 bytes, 12 out of which are occupied by a Java object header. Besides that, all Java objects are aligned by 8 bytes boundary. It means that, for example, an object containing 2 fields: <strong>int</strong> and <strong>byte</strong> will occupy not 17 (12 + 4 + 1), but 24 bytes (17 aligned by 8 bytes).</p>
<p>Each <strong>Object</strong> reference occupies 4 bytes if the Java heap is under 32G and<strong>XX:+UseCompressedOops</strong> is turned on (it is turned on by default in the recent Oracle JVM versions). Otherwise, <strong>Object</strong> references occupy 8 bytes.</p>
<p>All primitive data types occupy their exact byte size:</p>
<table border="1">
<tbody>
<tr>
<td>byte, boolean</td>
<td>1 byte</td>
</tr>
<tr>
<td>short, char</td>
<td>2 bytes</td>
</tr>
<tr>
<td>int, float</td>
<td>4 bytes</td>
</tr>
<tr>
<td>long, double</td>
<td>8 bytes</td>
</tr>
</tbody>
</table>
<p>In essence, this information is sufficient for Java memory optimization. But it will be more convenient if you will be aware of arrays / <strong>String</strong> / numeric wrappers memory consumption.</p>
<h2>Most common Java types memory consumption</h2>
<p>Arrays consume 12 bytes plus their length multiplied by their element size (and, of course, rounded by 8 bytes alignment).</p>
<p><a href="http://java-performance.info/changes-to-string-java-1-7-0_06/">From Java 7 build 06</a> <strong>String</strong> contains 3 fields – a <strong>char[]</strong> with the string data plus 2 <strong>int</strong> fields with 2 hash codes calculated by the different algorithms. It means that a <strong>String</strong> itself needs 12 (header) + 4 (<strong>char[]</strong> reference) + 4 * 2 (int) = 24 bytes (as you can see, it exactly fits in 8 byte alignment). Besides that, a <strong>char[]</strong> with the <strong>String</strong> data occupies 12 + length * 2 bytes (plus alignment). It means that a <strong>String</strong> occupies 36 + length*2 bytes aligned by 8 bytes (which is, by the way, 8 byte less than a <strong>String</strong> memory consumption prior to <a href="http://java-performance.info/changes-to-string-java-1-7-0_06/">Java 7 build 06</a>).</p>
<p>Numeric wrappers occupy 12 bytes plus size of the underlying type.<a href="http://java-performance.info/java-lang-byte-short-integer-long-character-boxing-and-unboxing/">Byte/Short/Character/Integer/Long are cached by JDK</a>, so the actual memory consumption may be smaller for values in the range [-128; 127]. Anyway, these type may be the source of serious memory overhead in the collection-based applications:</p>
<table border="1">
<tbody>
<tr>
<td>Byte, Boolean</td>
<td>16 bytes</td>
</tr>
<tr>
<td>Short, Character</td>
<td>16 bytes</td>
</tr>
<tr>
<td>Integer, Float</td>
<td>16 bytes</td>
</tr>
<tr>
<td>Long, Double</td>
<td>24 bytes</td>
</tr>
</tbody>
</table>
<h2>General Java memory optimization tips</h2>
<p>With all this knowledge at hand it is not difficult to give the general Java memory optimization tips:</p>
<ul>
<li>Prefer primitive types to their <strong>Object</strong> wrappers. The main cause of wrapper types usage are JDK collections, so consider using one of primitive type collection frameworks like<a href="http://java-performance.info/primitive-types-collections-trove-library/">Trove</a>.</li>
<li>Try to minimize number of <strong>Object</strong>s you have. For example, prefer array-based structures like <strong><a href="http://java-performance.info/arraylist-performance/">ArrayList</a>/<a href="http://java-performance.info/linkedlist-performance/">ArrayDeque</a></strong> to pointer based structures like <strong><a href="http://java-performance.info/linkedlist-performance/">LinkedList</a></strong>.</li>
</ul>
<h2>Java memory optimization example</h2>
<p>Here is an example. Suppose you have to create a map from <strong>int</strong> to 20 character long strings. The size of this map is equal to one million and all mappings are static and predefined (saved in some dictionary, for example).</p>
<p>The first approach is to use a <strong>Map&lt;Integer, String&gt;</strong> from the standard JDK. Let’s roughly estimate the memory consumption of this structure. Each <strong>Integer</strong> occupies 16 bytes plus 4 bytes for an <strong>Integer</strong> reference from a map. Each 20 character long <strong>String</strong> occupies 36 + 20*2 = 76 bytes (see <strong>String</strong> description above), which are aligned to 80 bytes. Plus 4 bytes for a reference. The total memory consumption will be roughly <b>(16 + 4 + 80 + 4) * 1M = 104M</b>.</p>
<p>The better approach will be replacing <strong>String</strong> with a <strong>byte[]</strong> in UTF-8 encoding as described in<a href="http://java-performance.info/string-packing-converting-characters-to-bytes/">String packing part 1: converting characters to bytes</a> article. Our map will be <strong>Map&lt;Integer, byte[]&gt;</strong>. Assume that all string characters belong to ASCII set (0-127), which is true in most of English-speaking countries. A <strong>byte[20]</strong> occupies 12 (header) + 20*1 = 32 bytes, which conveniently fit into 8 bytes alignment. The whole map will now occupy <b>(16 + 4 + 32 + 4) * 1M = 56M</b>, which is 2 times less than the previous example.</p>
<p>Now let’s use <a href="http://java-performance.info/primitive-types-collections-trove-library/">Trove</a> <strong>TIntObjectMap&lt;byte[]&gt;</strong>. It stores keys as normal <strong>int[]</strong> compared to wrapper types in JDK collections. Each key will now occupy exactly 4 bytes. The total memory consumption will go down to <b>(4 + 32 + 4) * 1M = 40M</b>.</p>
<p>The final structure will be more complicated. All <strong>String</strong> values will be stored in the single<strong>byte[]</strong> one after another with <strong>(byte)0</strong> as a separator (we still assume we have a text-based ASCII strings). The whole <strong>byte[]</strong> will occupy (20 + 1) * 1M = 21M. Our map will store an offset of the string in the large <strong>byte[]</strong> instead of the string itself. We will use Trove <strong>TIntIntMap</strong> for this purpose. It will consume (4 + 4) * 1M = 8M. The total memory consumption in this example will be <b>8M + 21M = 29M</b>. By the way, this is the first example relying on the immutability of this dataset.</p>
<p>Can we achieve the better result? Yes, we can, but at a cost of CPU consumption. The obvious ‘optimization’ is to sort the whole dataset by keys before storing values into a large <strong>byte[]</strong>. Now we may store the keys in the <strong>int[]</strong> and use a binary search to look for a key. If a key is found, its index multiplied by 21 (remember, all strings have the same length) will give us the offset of a value in the <strong>byte[]</strong>. This structure occupies ‘only’ <b>21M + 4M (for <strong>int[]</strong>) = 25M</b>at a price of <strong>O(log N)</strong> lookups compared to <strong>O(1)</strong> lookups in case of a hash map.</p>
<p>Is this the best we can do? No! We have forgotten that all values are 20 characters long, so we don’t actually need the separators in the <strong>byte[]</strong>. It means that we can store our ‘map’ using <b>24M memory</b> if we agree on <strong>O( log N )</strong> lookups. No overhead at all compared to theoretical data size and <b>nearly 4.5 times less than required by the original solution</b> (<strong>Map&lt;Integer, String&gt;</strong> )! Who told you that Java programs are memory hungry?</p>
<p>In <a href="http://java-performance.info/memory-consumption-of-java-data-types-1/">second part of this article</a> we will look at a few commonly used Java types memory consumption.</p>
<h2>Summary</h2>
<ul>
<li>Prefer primitive types to their <strong>Object</strong> wrappers. The main cause of wrapper types usage are JDK collections, so consider using one of primitive type collection frameworks like<a href="http://java-performance.info/primitive-types-collections-trove-library/">Trove</a>.</li>
<li>Try to minimize number of <strong>Object</strong>s you have. For example, prefer array-based structures like <strong><a href="http://java-performance.info/arraylist-performance/">ArrayList</a>/<a href="http://java-performance.info/linkedlist-performance/">ArrayDeque</a></strong> to pointer based structures like <strong><a href="http://java-performance.info/linkedlist-performance/">LinkedList</a></strong>.</li>
</ul>
<h2>Recommended reading</h2>
<p>If you want to find out more about the clever data compression algorithms, it worth to read<a href="http://www.amazon.com/gp/product/0201657880/ref=as_li_ss_tl?ie=UTF8&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0201657880&amp;linkCode=as2&amp;tag=javaperfor07e-20" rel="nofollow">“Programming Pearls” (second edition) by Jon Bentley</a><img alt="" src="http://www.assoc-amazon.com/e/ir?t=javaperfor07e-20&amp;l=as2&amp;o=1&amp;a=0201657880" width="1" height="1" border="0" />. This is a wonderful collection of rather unexpected algorithms. For example, in column 13.8 author has described how Doug McIlroy managed to fit a 75,000 word spellchecker just in 64 kilobytes of RAM. That spellchecker kept all required information in that tiny amount of memory and did not use disks! It may also be noticed that <a href="http://www.amazon.com/gp/product/0201657880/ref=as_li_ss_tl?ie=UTF8&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0201657880&amp;linkCode=as2&amp;tag=javaperfor07e-20" rel="nofollow">“Programming Pearls”</a><img alt="" src="http://www.assoc-amazon.com/e/ir?t=javaperfor07e-20&amp;l=as2&amp;o=1&amp;a=0201657880" width="1" height="1" border="0" /> is one of recommended preparation books for Google SRE interviews.</p>
<p>节选文章：</p>
<ul>
<li><a href="http://java-performance.info/overview-of-memory-saving-techniques-java/">An overview of memory saving techniques in Java</a></li>
<li><a href="http://java-performance.info/memory-consumption-of-java-data-types-1/">Memory consumption of popular Java data types – part 1</a></li>
<li><a href="http://java-performance.info/memory-consumption-of-java-data-types-2/">Memory consumption of java data types 2</a></li>
<li><a href="http://java-performance.info/java-collections-overview/">Java collections overview</a></li>
<li><a href="http://java-performance.info/a-few-more-memory-saving-techniques-in-java/">A few more memory saving techniques in Java</a></li>
</ul>
<p><a rel="nofollow" href="http://blog.zhourunsheng.com/2013/08/java%e5%bc%80%e5%8f%91%e5%86%85%e5%ad%98%e4%bc%98%e5%8c%96%e5%af%bc%e8%af%bb/">Java开发内存优化导读</a>，首发于<a rel="nofollow" href="http://blog.zhourunsheng.com">润物无声</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.zhourunsheng.com/2013/08/java%e5%bc%80%e5%8f%91%e5%86%85%e5%ad%98%e4%bc%98%e5%8c%96%e5%af%bc%e8%af%bb/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Java开发内存占用监测</title>
		<link>http://blog.zhourunsheng.com/2013/08/java%e5%bc%80%e5%8f%91%e5%86%85%e5%ad%98%e5%8d%a0%e7%94%a8%e7%9b%91%e6%b5%8b/</link>
		<comments>http://blog.zhourunsheng.com/2013/08/java%e5%bc%80%e5%8f%91%e5%86%85%e5%ad%98%e5%8d%a0%e7%94%a8%e7%9b%91%e6%b5%8b/#comments</comments>
		<pubDate>Mon, 05 Aug 2013 13:15:20 +0000</pubDate>
		<dc:creator><![CDATA[润物无声]]></dc:creator>
				<category><![CDATA[程序设计]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Memory]]></category>

		<guid isPermaLink="false">http://blog.zhourunsheng.com/?p=1729</guid>
		<description><![CDATA[<p>在开发Java的过程中，怎么样来监测一个对象占用的内存大小，对于调试程序，优化程序来说，有很大的帮助，本文介绍 [&#8230;]</p>
<p><a rel="nofollow" href="http://blog.zhourunsheng.com/2013/08/java%e5%bc%80%e5%8f%91%e5%86%85%e5%ad%98%e5%8d%a0%e7%94%a8%e7%9b%91%e6%b5%8b/">Java开发内存占用监测</a>，首发于<a rel="nofollow" href="http://blog.zhourunsheng.com">润物无声</a>。</p>
]]></description>
				<content:encoded><![CDATA[<p>在开发Java的过程中，怎么样来监测一个对象占用的内存大小，对于调试程序，优化程序来说，有很大的帮助，本文介绍了一个开发包，JAMM (Java Agent for Memory Measurements)，可以很方便的在程序的运行过程中动态监测对象的内存占用情况。<br />
This short article shows how to measure java object memory size at runtime with <a href="https://github.com/jbellis/jamm" target="_blank">JAMM</a>, a java agent dedicated to measure actual object memory use including JVM overhead.<br />
JAMM uses the <a href="http://docs.oracle.com/javase/6/docs/api/java/lang/instrument/Instrumentation.html" target="_blank">Instrumentation </a>implementation provided by the JVM to compute memory usage of a given object by calling the <a href="http://docs.oracle.com/javase/6/docs/api/java/lang/instrument/Instrumentation.html#getObjectSize(java.lang.Object)" target="_blank">getObjectSize(..)</a> method.<span id="more-1729"></span></p>
<p>It is quite simple to use, as explained by the author:</p>
<div>
<pre>        
MemoryMeter meter = new MemoryMeter();
meter.measure(object);
meter.measureDeep(object);
meter.countChildren(object);</pre>
</div>
<div>The only constraint is to attach JAMM java agent to the JVM before using it to measure memory usage, by starting the JVM with the <b>-javaagent</b> option pointing to the JAMM jar.</div>
<div></div>
<div>So, we are going to write a JUnit that shows how to use JAMM, but before we need to setup maven to achieve this:</div>
<div>
<pre>        
&lt; dependencies &gt; 
      &lt; dependency &gt; 
          &lt; groupid &gt;junit&lt;/ groupid &gt; 
          &lt; artifactid &gt;junit&lt;/ artifactid &gt; 
          &lt; version &gt;4.11&lt;/ version &gt; 
          &lt; scope &gt;test&lt;/ scope &gt; 
      &lt;/ dependency &gt; 

      &lt;!-- jamm java agent --&gt; 
      &lt; dependency &gt; 
          &lt; groupid &gt;com.github.stephenc&lt;/ groupid &gt; 
          &lt; artifactid &gt;jamm&lt;/ artifactid &gt; 
          &lt; version &gt;0.2.5&lt;/ version &gt; 
          &lt; scope &gt;test&lt;/ scope &gt; 
      &lt;/ dependency &gt; 

 &lt;/ dependencies &gt; 

 &lt; build &gt; 
      &lt; plugins &gt; 

          &lt;!-- copies java agent dependency into the target directory --&gt; 
          &lt; plugin &gt; 
              &lt; groupid &gt;org.apache.maven.plugins&lt;/ groupid &gt; 
              &lt; artifactid &gt;maven-dependency-plugin&lt;/ artifactid &gt; 
              &lt; version &gt;2.8&lt;/ version &gt; 
              &lt; executions &gt; 
                  &lt; execution &gt; 
                      &lt; id &gt;copy-dependencies&lt;/ id &gt; 
                      &lt; phase &gt;generate-test-resources&lt;/ phase &gt; 
                      &lt; goals &gt; 
                          &lt; goal &gt;copy&lt;/ goal &gt; 
                      &lt;/ goals &gt; 
                      &lt; configuration &gt; 
                          &lt; artifactitems &gt; 
                              &lt; artifactitem &gt; 
                                  &lt; groupid &gt;com.github.stephenc&lt;/ groupid &gt; 
                                  &lt; artifactid &gt;jamm&lt;/ artifactid &gt; 
                                  &lt; version &gt;0.2.5&lt;/ version &gt; 
                                  &lt; type &gt;jar&lt;/ type &gt; 
                                  &lt; outputdirectory &gt;${project.build.directory}&lt;/ outputdirectory &gt; 
                                  &lt; destfilename &gt;jamm.jar&lt;/ destfilename &gt; 
                              &lt;/ artifactitem &gt; 
                          &lt;/ artifactitems &gt; 
                      &lt;/ configuration &gt; 
                  &lt;/ execution &gt; 
              &lt;/ executions &gt; 
          &lt;/ plugin &gt; 

          &lt;!-- executes test with java agent options of the JVM --&gt; 
          &lt; plugin &gt; 
              &lt; groupid &gt;org.apache.maven.plugins&lt;/ groupid &gt; 
              &lt; artifactid &gt;maven-surefire-plugin&lt;/ artifactid &gt; 
              &lt; version &gt;2.14&lt;/ version &gt; 
              &lt; configuration &gt; 
                  &lt; argline &gt;-javaagent:${project.build.directory}/jamm.jar&lt;/ argline &gt; 
              &lt;/ configuration &gt; 
          &lt;/ plugin &gt; 

      &lt;/ plugins &gt; 
 &lt;/ build &gt;</pre>
</div>
<p>Next, write the following JUnit that explores the JAMM features:</p>
<div>
<pre> package org.javabenchmark.memory; 

 import java.util.ArrayList; 
 import java.util.List; 
 import org.github.jamm.MemoryMeter; 
 import org.junit.Test; 

 public class MemoryMeterTest { 

      private MemoryMeter meter = new MemoryMeter(); 

      @Test 
      public void shouldMeasureMemoryUsage() { 

          String st1 = "This is the string #1" ; 
          measure(st1); 

          String st2 = "This is the string #2 and it has more chars." ; 
          measure(st2); 

          List aList = new ArrayList( 0 ); 
          measure(aList); 

          aList.add(st1); 
          measure(aList); 

          aList.add(st2); 
          measure(aList); 
      } 

      private void measure(Object anObject) { 
          System.out.println( "-----------------------------------" ); 
          System.out.printf( "size: %d bytes\n" , meter.measure(anObject)); 
          System.out.printf( "retained size: %d bytes\n" , meter.measureDeep(anObject)); 
          System.out.printf( "inner object count: %d\n" , meter.countChildren(anObject)); 
      } 
 }</pre>
</div>
<p>Running the test produces the following output on my computer:</p>
<div>
<pre> ----------------------------------- 
 size: 24 bytes 
 retained size: 88 bytes 
 inner object count: 2 
 ----------------------------------- 
 size: 24 bytes 
 retained size: 128 bytes 
 inner object count: 2 
 ----------------------------------- 
 size: 24 bytes 
 retained size: 40 bytes 
 inner object count: 2 
 ----------------------------------- 
 size: 24 bytes 
 retained size: 136 bytes 
 inner object count: 4 
 ----------------------------------- 
 size: 24 bytes 
 retained size: 264 bytes 
 inner object count: 6</pre>
</div>
<p>To conclude, you can see how it is easy to monitor the memory usage of your objects. It is very handy when dealing with huge collections, or when using caches such as the ones provided by Guava or EHCache. That way you can setup trigger that alert when memory consumption is excessive.</p>
<p><strong>注意：</strong></p>
<p>如果在调试的过程中，发现内存不足的情况，请调整JVM的启动参数。</p>
<p>JVM options: <b>-Xms256m -Xmx256m</b>.</p>
<p>文章选自：<a href="http://blog.javabenchmark.org/2013/07/compute-java-object-memory-footprint-at.html">compute-java-object-memory-footprint-at.html</a></p>
<p><a rel="nofollow" href="http://blog.zhourunsheng.com/2013/08/java%e5%bc%80%e5%8f%91%e5%86%85%e5%ad%98%e5%8d%a0%e7%94%a8%e7%9b%91%e6%b5%8b/">Java开发内存占用监测</a>，首发于<a rel="nofollow" href="http://blog.zhourunsheng.com">润物无声</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.zhourunsheng.com/2013/08/java%e5%bc%80%e5%8f%91%e5%86%85%e5%ad%98%e5%8d%a0%e7%94%a8%e7%9b%91%e6%b5%8b/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
