<html 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=us-ascii">
<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:DengXian;
        panose-1:2 1 6 0 3 1 1 1 1 1;}
@font-face
        {font-family:Aptos;
        panose-1:2 11 0 4 2 2 2 2 2 4;}
@font-face
        {font-family:"\@DengXian";
        panose-1:2 1 6 0 3 1 1 1 1 1;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        font-size:10.0pt;
        font-family:"Aptos",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:#467886;
        text-decoration:underline;}
p.p1, li.p1, div.p1
        {mso-style-name:p1;
        mso-margin-top-alt:auto;
        margin-right:0cm;
        mso-margin-bottom-alt:auto;
        margin-left:0cm;
        font-size:12.0pt;
        font-family:"Aptos",sans-serif;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;
        mso-ligatures:none;}
@page WordSection1
        {size:612.0pt 792.0pt;
        margin:72.0pt 72.0pt 72.0pt 72.0pt;}
div.WordSection1
        {page:WordSection1;}
--></style>
</head>
<body lang="EN-GB" link="#467886" vlink="#96607D" style="word-wrap:break-word">
<div class="WordSection1">
<p class="p1">Post to <a href="mailto:hotspot-compiler-dev@openjdk.org">hotspot-compiler-dev@openjdk.org</a> instead of
<a href="mailto:hotspot-compiler-dev@openjdk.java.net">hotspot-compiler-dev@openjdk.java.net</a>.</p>
<p class="p1">Sorry for the repetition.</p>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
<div id="mail-editor-reference-message-container">
<div>
<div>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0cm 0cm 0cm">
<p class="MsoNormal" style="margin-bottom:12.0pt"><b><span style="font-size:12.0pt;color:black">From:
</span></b><span style="font-size:12.0pt;color:black">Fei Gao <Fei.Gao2@arm.com><br>
<b>Date: </b>Friday, 26 September 2025 at 14:52<br>
<b>To: </b>leyden-dev <leyden-dev@openjdk.org>, hotspot compiler <hotspot-compiler-dev@openjdk.java.net><br>
<b>Subject: </b>Leverage profiled compiled size to avoid aggressive inlining and code growth<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">Hi </span><a id="OWAAMAE9C2F678A97D045B3FD3495AFA23F10" href="mailto:leyden-dev@openjdk.org"><span style="font-size:11.0pt;font-family:"Aptos",sans-serif;text-decoration:none">@leyden-dev</span></a><span style="font-size:11.0pt">
 and </span><a id="OWAAMC8ABEC836EA79E4EB7B9B1AE22716945" href="mailto:hotspot-compiler-dev@openjdk.java.net"><span style="font-size:11.0pt;font-family:"Aptos",sans-serif;text-decoration:none">@hotspot compiler</span></a><span style="font-size:11.0pt">,</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><b><span style="font-size:11.0pt">TL;DR</span></b><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><b><span style="font-size:11.0pt"> </span></b><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><a href="https://github.com/openjdk/jdk/pull/27527"><b><span style="font-size:11.0pt">https://github.com/openjdk/jdk/pull/27527</span></b></a><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">I proposed a PoC that explores leveraging profiled compiled sizes to improve C2 inlining decisions and mitigate code bloat. The approach records method sizes during a pre-run and feeds them back via compiler
 directives, helping to reduce aggressive inlining of large methods.</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">Testing on Renaissance and SPECjbb2015 showed clear code size differences but no significant performance impact on either AArch64 or x86. An alternative AOT-cache-based approach was also evaluated but did
 not produce meaningful code size changes.</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">Open questions remain about the long-term value of profiling given Project Leyden's direction of caching compiled code in AOT, and whether global profiling information could help C2 make better inlining decisions.</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><b><span style="font-size:11.0pt">1. Motivation</span></b><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">In the current C2 behavior, the inliner only considers the estimated inlined size [1] [2] of a callee if the method has already been compiled by C2. In particular, C2 will explicitly reject inlining in the
 following cases:</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">    Hot methods with bytecode size > FreqInlineSize (325) [3]</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">    Cold methods with bytecode size > MaxInlineSize (35)</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">However, a common situation arises where a method's bytecode size is below 325, yet once compiled by C2 it produces a very large machine code body. If this method has not been compiled at the time its caller
 is being compiled, the inliner may aggressively inline it, potentially bloating the caller, even though an independent compiled copy might eventually exist.</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">To mitigate such cases, we can make previously profiled compiled sizes available early, allowing the inliner to make more informed decisions and reduce excessive code growth.</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">[1] </span><a href="https://github.com/openjdk/jdk/blob/0ba4141cb12414c08be88b37ea2a163aacbfa7de/src/hotspot/share/opto/bytecodeInfo.cpp#L180"><span style="font-size:11.0pt">https://github.com/openjdk/jdk/blob/0ba4141cb12414c08be88b37ea2a163aacbfa7de/src/hotspot/share/opto/bytecodeInfo.cpp#L180</span></a><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">[2] </span><a href="https://github.com/openjdk/jdk/blob/0ba4141cb12414c08be88b37ea2a163aacbfa7de/src/hotspot/share/opto/bytecodeInfo.cpp#L274"><span style="font-size:11.0pt">https://github.com/openjdk/jdk/blob/0ba4141cb12414c08be88b37ea2a163aacbfa7de/src/hotspot/share/opto/bytecodeInfo.cpp#L274</span></a><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">[3] </span><a href="https://github.com/openjdk/jdk/blob/0ba4141cb12414c08be88b37ea2a163aacbfa7de/src/hotspot/share/opto/bytecodeInfo.cpp#L184"><span style="font-size:11.0pt">https://github.com/openjdk/jdk/blob/0ba4141cb12414c08be88b37ea2a163aacbfa7de/src/hotspot/share/opto/bytecodeInfo.cpp#L184</span></a><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><b><span style="font-size:11.0pt">2. Proof of Concept</span></b><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">To validate this idea, I created a proof-of-concept:
</span><a href="https://github.com/openjdk/jdk/pull/27527"><b><span style="font-size:11.0pt">https://github.com/openjdk/jdk/pull/27527</span></b></a><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">In this PoC:</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">1) A dumping interface was added to record C2-compiled method sizes, enabled via the `-XX:+PrintOptoMethodSize` flag.</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">2) A new attribute was introduced in InlineMatcher: _inline_instructions_size. This attribute stores the estimated inlined size of a method, sourced from a compiler directive JSON file generated during a prior
 profiling run.</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">3) The inliner was updated to use these previously profiled method sizes to prevent aggressive inlining of large methods.</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><b><span style="font-size:11.0pt">3. How to Use</span></b><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">To apply this approach to any workload, the workload must be run twice:
</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">1) Pre-run: collect inlined sizes for all C2-compiled methods.
</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">2) Product run: use the profiled method sizes to improve C2 inlining.</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">Step 1 Profile method size (pre-run)</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">Log the compiled method size:</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">`-XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:+PrintOptoMethodSize -XX:LogFile=logmethodsize.out` This will generate a log containing method size information from C2.</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">Step 2 Generate the compiler directive file</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">Use the provided Python script to extract method size info and generate a JSON file:</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">`python3 extract_size_to_directives.py logmethodsize.out output_directives.json`</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">This file contains estimated inlined sizes to guide inlining decisions in product run. If the same method is compiled multiple times, the script conservatively retains the smallest observed size.
</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">Note: Methods that are not accepted by the CompilerDirective format need to be excluded.</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">Step 3 Use the compiler directive in a product run</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">Pass the generated JSON to the JVM as a directive:</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">`-XX:+UnlockDiagnosticVMOptions -XX:CompilerDirectivesFile=output_directives.json`
</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">This enables the inliner to make decisions using previously profiled method sizes, potentially avoiding aggressive inlining of large methods.</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">Note: The patch reuses the existing `inline` directive attribute for inlining control. If multiple inline rules match the same method, only the first match is effective.</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><b><span style="font-size:11.0pt">4. Testing</span></b><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">I tested the following workloads using the method above and measured the code cache size with `-XX:+PrintCodeCache`. The results are shown below, compared against the mainline code. All statistics (min, max,
 median, mean) are based on three runs.</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">(patch - mainline) / mainline</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">1) Renaissance.dotty</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">Code size change:</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">AArch64:</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">```</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">used           min      max      median   mean</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">non-profiled   -9.88%   -8.13%   -8.92%   -8.98%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">profiled       -0.73%   -0.21%   -0.40%   -0.45%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">non-nmethods   -15.20%  -0.02%   -14.92%   -10.32%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">codecache      -2.82%   -2.88%   -2.97%   -2.89%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">max_used       min      max      median   mean</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">non-profiled   -9.88%   -8.13%   -8.92%   -8.98%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">profiled       2.37%    1.41%    1.50%    1.76%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">non-nmethods   -0.95%   -1.73%   -0.93%   -1.21%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">codecache      -0.35%   -1.00%   -0.95%   -0.77%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">```</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">X86:</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">```</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">used            min      max      median   mean</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">non-profiled    -9.72%   -9.61%   -9.36%   -9.56%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">profiled        -0.81%   -0.90%   -1.15%   -0.95%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">non-nmethods    -0.04%   0.04%    -0.02%   -0.01%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">codecache       -2.94%   -2.96%   -3.11%   -3.00%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">max_used        min      max      median   mean</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">non-profiled    -9.72%   -9.61%   -9.36%   -9.56%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">profiled        2.32%    2.60%    2.51%    2.48%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">non-nmethods    -0.63%   -2.25%   -1.28%   -1.39%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">codecache       -0.68%   -0.59%   -0.70%   -0.66%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">```</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">No significant performance changes were observed on either platform.</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">2) SPECjbb 2015</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">Code size change:</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">AArch64:</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">```</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">used           min      max       median    mean</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">non-profiled   -1.00%   -11.68%   -12.73%   -8.62%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">profiled       9.07%    -6.93%    -2.34%    -0.29%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">non-nmethods   0.02%    -0.02%    0.00%     0.00%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">codecache      2.98%    -7.18%    -5.35%    -3.28%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">max_used       min      max       median    mean</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">non-profiled   -10.85%  -11.68%   -12.73%   -11.76%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">profiled       -2.09%   -11.65%   -1.26%   -5.62%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">non-nmethods   0.13%    -1.21%    -0.16%   -0.41%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">codecache      -6.42%   -6.33%    -6.10%   -6.29%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">```</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">On the AArch64 platform, no significant performance changes were observed for either high-bound IR or max jOPS.</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">For critical jOPS:</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">```</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">Min      Median   Mean     Max     Var%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">-2.45%   -1.87%   -2.45%   -3.00%  1.9%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">```</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">X86:</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">```</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">used           min      max      median   mean</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">non-profiled   -9.02%   -9.65%   -7.93%   -8.87%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">profiled       -6.09%   -3.18%   -4.52%   -4.61%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">non-nmethods   -0.02%   0.25%    0.04%    0.09%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">codecache      -5.36%   -4.75%   -4.58%   -4.90%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">max_used       min      max      median   mean</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">non-profiled   -4.03%   -9.65%   -7.93%   -7.23%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">profiled       -2.86%   1.16%    -1.03%   -0.93%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">non-nmethods   0.02%    -0.08%   0.08%    0.01%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">codecache      -0.23%   -4.20%   -3.70%   -2.73%</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">```</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">No significant performance change was observed on x86 platform.</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><b><span style="font-size:11.0pt">5. AOT cache</span></b><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">The current procedure above requires three steps:</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">a pre-run to record method sizes,</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">a separate step to process the JSON file,</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">and finally a product run using the profiled method sizes.</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">This workflow may add extra burden to workload deployment.</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">With JEP 515 [4], we can instead store the estimated inlined size in the AOT cache when ciMethod::inline_instructions_size() is called during the premain run, and later load this size from the AOT cache during
 the product run [5].</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">The store-load mechanism for inlined size can help reduce the overhead of recomputing actual sizes, but it does not provide the inliner with much additional information about the callee, since the compilation
 order in the product run generally follows that of the premain run, even if not exactly.</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">To give the inliner more profiled information about callees, I tried another simple draft that records inlined sizes for more C2-compiled methods:</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><a href="https://github.com/openjdk/jdk/pull/27519/commits/ef5e61f3d68ad565ee11e2cc6aa57b6e2697ae6d"><span style="font-size:11.0pt">https://github.com/openjdk/jdk/pull/27519/commits/ef5e61f3d68ad565ee11e2cc6aa57b6e2697ae6d</span></a><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">However, with this draft using the AOT cache, I did not observe any significant code size changes for any workloads. This may require further investigation.</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">[4] </span><a href="https://openjdk.org/jeps/515"><span style="font-size:11.0pt">https://openjdk.org/jeps/515</span></a><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">[5] </span><a href="https://github.com/openjdk/jdk/blob/0ba4141cb12414c08be88b37ea2a163aacbfa7de/src/hotspot/share/ci/ciMethod.cpp#L1152"><span style="font-size:11.0pt">https://github.com/openjdk/jdk/blob/0ba4141cb12414c08be88b37ea2a163aacbfa7de/src/hotspot/share/ci/ciMethod.cpp#L1152</span></a><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><b><span style="font-size:11.0pt">6 Questions</span></b><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">1) Relation to Project Leyden</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">Project Leyden aims to enhance the AOT cache to store compiled code from training runs [6]. This suggests that we may eventually prefer to cache compiled code directly from the AOT cache rather than rely solely
 on JIT compilation.</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">Given this direction, is it still worthwhile to invest further in using profiled method sizes as a means to improve inlining heuristics?</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">Could such profiling provide complementary benefits even if compiled code is cached?</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">2) Global profiling information for C2</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">Should we consider leveraging profiled information stored in the AOT cache to give the C2 inliner a broader, more global view of methods, enabling better inlining decisions?</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">For example, could global visibility into method sizes and call sites help address pathological cases of code bloat or missed optimization opportunities? [7]</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">[6] </span><a href="https://openjdk.org/jeps/8335368"><span style="font-size:11.0pt">https://openjdk.org/jeps/8335368</span></a><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">[7] </span><a href="https://wiki.openjdk.org/display/hotspot/inlining"><span style="font-size:11.0pt">https://wiki.openjdk.org/display/hotspot/inlining</span></a><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">I'd greatly appreciate any feedback. Thank you for your time and consideration.</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">Thanks,</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt">Fei</span><span style="font-size:12.0pt"><o:p></o:p></span></p>
</div>
</div>
</div>
</div>
</div>
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose,
 or store or copy the information in any medium. Thank you.
</body>
</html>