<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>