<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
{font-family:Consolas;
panose-1:2 11 6 9 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0cm;
margin-bottom:.0001pt;
font-size:12.0pt;
font-family:"Times New Roman",serif;
color:black;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-priority:99;
color:purple;
text-decoration:underline;}
pre
{mso-style-priority:99;
mso-style-link:"HTML Preformatted Char";
margin:0cm;
margin-bottom:.0001pt;
font-size:10.0pt;
font-family:"Courier New";
color:black;}
span.HTMLPreformattedChar
{mso-style-name:"HTML Preformatted Char";
mso-style-priority:99;
mso-style-link:"HTML Preformatted";
font-family:Consolas;
color:black;}
span.EmailStyle19
{mso-style-type:personal-reply;
font-family:"Calibri",sans-serif;
color:#1F497D;}
.MsoChpDefault
{mso-style-type:export-only;
font-size:10.0pt;}
@page WordSection1
{size:612.0pt 792.0pt;
margin:70.85pt 70.85pt 2.0cm 70.85pt;}
div.WordSection1
{page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body bgcolor="white" lang="DE" link="blue" vlink="purple">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US">Thanks, Jon.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US">I have created a webrev:
</span><a href="http://cr.openjdk.java.net/~goetz/wr16/8151101_paroldgc_parallelization_of_large_obj_arrays/webrev/"><span lang="EN-US">http://cr.openjdk.java.net/~goetz/wr16/8151101_paroldgc_parallelization_of_large_obj_arrays/webrev/</span></a><span lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US">Regards,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D;mso-fareast-language:EN-US">Richard.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<div>
<div style="border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0cm 0cm 0cm">
<p class="MsoNormal"><b><span lang="EN-US" style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:windowtext">From:</span></b><span lang="EN-US" style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:windowtext"> hotspot-gc-dev [mailto:hotspot-gc-dev-bounces@openjdk.java.net]
<b>On Behalf Of </b>Jon Masamitsu<br>
<b>Sent:</b> Donnerstag, 3. März 2016 00:34<br>
<b>To:</b> hotspot-gc-dev@openjdk.java.net<br>
<b>Subject:</b> Re: Performance bug in and XXS patch for Parallel Old GC scanning large object arrays<o:p></o:p></span></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal" style="margin-bottom:12.0pt">Richard,<br>
<br>
I've created <br>
<br>
<a href="https://bugs.openjdk.java.net/browse/JDK-8151101">https://bugs.openjdk.java.net/browse/JDK-8151101</a><br>
<br>
and attached your mail to it.<br>
<br>
Jon<o:p></o:p></p>
<div>
<p class="MsoNormal">On 03/02/2016 04:26 AM, Reingruber, Richard wrote:<o:p></o:p></p>
</div>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<pre>Hi,<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre>I would like to report a performance bug in the parallel old collector handling<o:p></o:p></pre>
<pre>large object arrays and contribute an XXS patch for the bug that improves gc pauses by<o:p></o:p></pre>
<pre>5x in a microbenchmark. The problem is that scanning of large object arrays is<o:p></o:p></pre>
<pre>not really parallelized.<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre>When marking through large object arrays, the elements are scanned in chunks of<o:p></o:p></pre>
<pre>ObjArrayMarkingStride. This is done in<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre>ObjArrayKlass::objarray_follow_contents(ParCompactionManager* cm, oop obj, int index)<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre>In particular, the partially scanned array is pushed on the _objarray_stack only<o:p></o:p></pre>
<pre>*after* the elements are marked and pushed on the marking stack. It would help<o:p></o:p></pre>
<pre>parallelizing the work, if the array was made available to other threads (by<o:p></o:p></pre>
<pre>pushing it on _objarray_stack) *before* the current thread visits its stride of<o:p></o:p></pre>
<pre>elements.<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre>diff -r 5c4f8192021e src/share/vm/gc/parallel/psCompactionManager.inline.hpp<o:p></o:p></pre>
<pre>--- a/src/share/vm/gc/parallel/psCompactionManager.inline.hpp Tue Mar 01 09:42:19 2016 +0100<o:p></o:p></pre>
<pre>+++ b/src/share/vm/gc/parallel/psCompactionManager.inline.hpp Wed Mar 02 12:17:07 2016 +0100<o:p></o:p></pre>
<pre>@@ -125,14 +125,14 @@<o:p></o:p></pre>
<pre> T* const beg = base + beg_index;<o:p></o:p></pre>
<pre> T* const end = base + end_index;<o:p></o:p></pre>
<pre> <o:p></o:p></pre>
<pre>+ if (end_index < len) {<o:p></o:p></pre>
<pre>+ cm->push_objarray(obj, end_index); // Push the continuation.<o:p></o:p></pre>
<pre>+ }<o:p></o:p></pre>
<pre>+<o:p></o:p></pre>
<pre> // Push the non-NULL elements of the next stride on the marking stack.<o:p></o:p></pre>
<pre> for (T* e = beg; e < end; e++) {<o:p></o:p></pre>
<pre> cm->mark_and_push<T>(e);<o:p></o:p></pre>
<pre> }<o:p></o:p></pre>
<pre>-<o:p></o:p></pre>
<pre>- if (end_index < len) {<o:p></o:p></pre>
<pre>- cm->push_objarray(obj, end_index); // Push the continuation.<o:p></o:p></pre>
<pre>- }<o:p></o:p></pre>
<pre> }<o:p></o:p></pre>
<pre> <o:p></o:p></pre>
<pre> inline void ParCompactionManager::follow_contents(objArrayOop obj, int index) {<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre>Below you can find a microbenchmark that demonstrates the performance bug and<o:p></o:p></pre>
<pre>the output of 2 runs without and with the patch on a linux x86_64 box with 32 hw<o:p></o:p></pre>
<pre>threads and 16 cores.<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre>I'd suggest as well to reduce ObjArrayMarkingStride (512 by dflt) for the<o:p></o:p></pre>
<pre>parallel old gc for better parallelization. G1 and the parallel scavenger for<o:p></o:p></pre>
<pre>example use ParGCArrayScanChunk of 50). Both push the remainder *before*<o:p></o:p></pre>
<pre>iterating the array.<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre>Regards,<o:p></o:p></pre>
<pre>Richard.<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre>--<o:p></o:p></pre>
<pre>Richard Reingruber | SAP JVM | CORE PLATFORM, SAP SE <o:p></o:p></pre>
<pre>Pflichtangaben/Mandatory Disclosure Statements: <a href="http://www.sap.com/company/legal/impressum.epx">http://www.sap.com/company/legal/impressum.epx</a> <o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre>###<o:p></o:p></pre>
<pre>### Benchmark Run 1 without the path<o:p></o:p></pre>
<pre>###<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre><o:p> </o:p></pre>
<pre>$ ./jdk9/bin/java -showversion -Xms8g -Xmx8g -XX:+UseParallelOldGC -cp /usr/work/d038402/jtests/QuickJavaTests/bin test.gc.TestLargeObjectArray 20 100000 4<o:p></o:p></pre>
<pre>openjdk version "9-internal"<o:p></o:p></pre>
<pre>OpenJDK Runtime Environment (build 9-internal+0-2016-03-01-165700.d038402.hs-rt)<o:p></o:p></pre>
<pre>OpenJDK 64-Bit Server VM (build 9-internal+0-2016-03-01-165700.d038402.hs-rt, mixed mode)<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre>Building large array with 100000 elements of small trees with depth 4<o:p></o:p></pre>
<pre>Heap stats: free:7769 MB (99.0 %) max:7851 MB<o:p></o:p></pre>
<pre>done<o:p></o:p></pre>
<pre>Heap stats: free:6417 MB (81.7 %) max:7851 MB<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 8759 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 1856 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 3657 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 4280 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 1823 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 2439 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 1803 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 1675 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 1889 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 1867 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 1854 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 1771 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 1792 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 1681 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 1844 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 1807 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 1832 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 1835 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 1953 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 1846 ms<o:p></o:p></pre>
<pre>d038402@ld3357 [/net/usr.work/d038402/tmp] 17:55:04<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre>###<o:p></o:p></pre>
<pre>### Benchmark Run 2 without the path<o:p></o:p></pre>
<pre>###<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre>$ ./jdk9_mod/bin/java -showversion -Xms8g -Xmx8g -XX:+UseParallelOldGC -cp /usr/work/d038402/jtests/QuickJavaTests/bin test.gc.TestLargeObjectArray 20 100000 4<o:p></o:p></pre>
<pre>openjdk version "9-internal"<o:p></o:p></pre>
<pre>OpenJDK Runtime Environment (build 9-internal+0-2016-03-01-165700.d038402.hs-rt)<o:p></o:p></pre>
<pre>OpenJDK 64-Bit Server VM (build 9-internal+0-2016-03-01-165700.d038402.hs-rt, mixed mode)<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre>Building large array with 100000 elements of small trees with depth 4<o:p></o:p></pre>
<pre>Heap stats: free:7769 MB (99.0 %) max:7851 MB<o:p></o:p></pre>
<pre>done<o:p></o:p></pre>
<pre>Heap stats: free:6376 MB (81.2 %) max:7851 MB<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 3684 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 1073 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 425 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 369 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 436 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 334 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 352 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 420 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 391 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 393 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 356 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 352 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 348 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 354 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 340 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 370 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 363 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 370 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 355 ms<o:p></o:p></pre>
<pre>Calling System.gc()<o:p></o:p></pre>
<pre>Heap stats: free:6467 MB (82.4 %) max:7851 MB<o:p></o:p></pre>
<pre>Full GC duration: 348 ms<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre>###<o:p></o:p></pre>
<pre>### Benchmark source code<o:p></o:p></pre>
<pre>###<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre>package test.gc;<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre>public class TestLargeObjectArray {<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre> private static final long MB = 1 << 20;<o:p></o:p></pre>
<pre> private int arraySize;<o:p></o:p></pre>
<pre> private int treeDepth;<o:p></o:p></pre>
<pre> private int iterations;<o:p></o:p></pre>
<pre> private LittleTree[] arrayOfSmallTrees;<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre> public static void main(String[] args) {<o:p></o:p></pre>
<pre> TestLargeObjectArray test = new TestLargeObjectArray();<o:p></o:p></pre>
<pre> test.parseCmdLine(args);<o:p></o:p></pre>
<pre> test.buildLargeArrayOfSmallTrees();<o:p></o:p></pre>
<pre> test.run();<o:p></o:p></pre>
<pre> }<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre> private void run() {<o:p></o:p></pre>
<pre> while (iterations-- > 0) {<o:p></o:p></pre>
<pre> long start = System.currentTimeMillis();<o:p></o:p></pre>
<pre> message("Calling System.gc()");<o:p></o:p></pre>
<pre> System.gc();<o:p></o:p></pre>
<pre> long end = System.currentTimeMillis();<o:p></o:p></pre>
<pre> heapStats();<o:p></o:p></pre>
<pre> message("Full GC duration: " + (end - start) + " ms");<o:p></o:p></pre>
<pre> }<o:p></o:p></pre>
<pre> }<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre> public void buildLargeArrayOfSmallTrees() {<o:p></o:p></pre>
<pre> try {<o:p></o:p></pre>
<pre> message("Building large array with " + arraySize + " elements of small trees with depth " + treeDepth);<o:p></o:p></pre>
<pre> heapStats();<o:p></o:p></pre>
<pre> arrayOfSmallTrees = new LittleTree[arraySize];<o:p></o:p></pre>
<pre> for (int i = 0; i < arraySize; i++) {<o:p></o:p></pre>
<pre> arrayOfSmallTrees[i] = LittleTree.build(treeDepth);<o:p></o:p></pre>
<pre> }<o:p></o:p></pre>
<pre> message("done");<o:p></o:p></pre>
<pre> heapStats();<o:p></o:p></pre>
<pre> } catch (OutOfMemoryError oom) {<o:p></o:p></pre>
<pre> arrayOfSmallTrees = null;<o:p></o:p></pre>
<pre> message("OutOfMemory: please reduce array size or tree depth");<o:p></o:p></pre>
<pre> System.exit(1);<o:p></o:p></pre>
<pre> }<o:p></o:p></pre>
<pre> }<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre> private void heapStats() {<o:p></o:p></pre>
<pre> long free = Runtime.getRuntime().freeMemory();<o:p></o:p></pre>
<pre> long max = Runtime.getRuntime().maxMemory();<o:p></o:p></pre>
<pre> float freePercentage = round((float) free / (float) max * 100);<o:p></o:p></pre>
<pre> message("Heap stats: free:" + free / MB + " MB (" + freePercentage + " %)" + " max:" + max / MB + " MB");<o:p></o:p></pre>
<pre> }<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre> private float round(float f) {<o:p></o:p></pre>
<pre> return Math.round(f * 10) / 10f;<o:p></o:p></pre>
<pre> }<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre> private void parseCmdLine(String[] args) {<o:p></o:p></pre>
<pre> if (args.length != 3) {<o:p></o:p></pre>
<pre> message();<o:p></o:p></pre>
<pre> message("usage: java " + TestLargeObjectArray.class.getName()<o:p></o:p></pre>
<pre> + " <test iterations, e.g. 20> <large array size, e.g. 50000> <small tree depth, e.g. 4>");<o:p></o:p></pre>
<pre> message();<o:p></o:p></pre>
<pre> System.exit(1);<o:p></o:p></pre>
<pre> }<o:p></o:p></pre>
<pre> int i = 0;<o:p></o:p></pre>
<pre> iterations = Integer.parseInt(args[i++]);<o:p></o:p></pre>
<pre> arraySize = Integer.parseInt(args[i++]);<o:p></o:p></pre>
<pre> treeDepth = Integer.parseInt(args[i++]);<o:p></o:p></pre>
<pre> }<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre> private void message(String msg) {<o:p></o:p></pre>
<pre> System.out.println(msg);<o:p></o:p></pre>
<pre> }<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre> private void message() {<o:p></o:p></pre>
<pre> System.out.println();<o:p></o:p></pre>
<pre> }<o:p></o:p></pre>
<pre>}<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre>class LittleTree {<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre> private static final int ARITY = 6;<o:p></o:p></pre>
<pre> @SuppressWarnings("unused")<o:p></o:p></pre>
<pre> private LittleTree[] subtrees;<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre> public LittleTree(LittleTree[] trees) {<o:p></o:p></pre>
<pre> this.subtrees = trees;<o:p></o:p></pre>
<pre> }<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre> public static LittleTree build(int treeDepth) {<o:p></o:p></pre>
<pre> if (treeDepth == 0) {<o:p></o:p></pre>
<pre> return null;<o:p></o:p></pre>
<pre> }<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre> // recursion<o:p></o:p></pre>
<pre> LittleTree[] subtrees = new LittleTree[ARITY];<o:p></o:p></pre>
<pre> for (int i = 0; i < ARITY; i++) {<o:p></o:p></pre>
<pre> subtrees[i] = build(treeDepth - 1);<o:p></o:p></pre>
<pre> }<o:p></o:p></pre>
<pre> return new LittleTree(subtrees);<o:p></o:p></pre>
<pre> }<o:p></o:p></pre>
<pre>}<o:p></o:p></pre>
</blockquote>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
</body>
</html>