RFR: 8336856: Optimize String Concat [v39]

Shaojin Wen duke at openjdk.org
Fri Aug 9 05:58:40 UTC 2024


On Thu, 8 Aug 2024 11:43:07 GMT, Shaojin Wen <duke at openjdk.org> wrote:

>> This PR implements the same algorithm as the current generateMHInlineCopy based on bytecode to improve startup performance.
>
> Shaojin Wen has updated the pull request incrementally with one additional commit since the last revision:
> 
>   fix comments

I've found a way to verify that unloading of the hidden concat classes works.

Run the following code:


import java.lang.invoke.*;

public class HiddenClassUnloading {
    public static void main(String[] args) throws Throwable {
        MethodHandles.Lookup lookup = MethodHandles.lookup();

        Class<?>[] types = new Class[] {
                int.class, long.class, double.class, float.class, char.class, boolean.class, String.class,
        };
        Object[] values = new Object[] {
                1, 1L, 1D, 1F, 'C', true, "A",
        };

        int sum = 0;
        for (int i = 0; i < 1_000_000; i++) {
            int radix = types.length;
            String str = Integer.toString(i, radix);
            int length = str.length();
            String recipe = "\1".repeat(length);
            Class<?>[] ptypes = new Class[length];
            Object[] pvalues = new Object[length];
            for (int j = 0; j < length; j++) {
                int index = Integer.parseInt(str.substring(j, j + 1), radix);
                ptypes[j] = types[index];
                pvalues[j] = values[index];
            }
            MethodType concatType = MethodType.methodType(String.class, ptypes);
            CallSite callSite = StringConcatFactory.makeConcatWithConstants(
                    lookup,
                    "concat",
                    concatType,
                    recipe,
                    new Object[0]
            );
            MethodHandle mh = callSite.dynamicInvoker();
            String result = switch (length) {
                case 1 -> (String) mh.invoke(pvalues[0]);
                case 2 -> (String) mh.invoke(pvalues[0], pvalues[1]);
                case 3 -> (String) mh.invoke(pvalues[0], pvalues[1], pvalues[2]);
                case 4 -> (String) mh.invoke(pvalues[0], pvalues[1], pvalues[2], pvalues[3]);
                case 5 -> (String) mh.invoke(pvalues[0], pvalues[1], pvalues[2], pvalues[3], pvalues[4]);
                case 6 -> (String) mh.invoke(pvalues[0], pvalues[1], pvalues[2], pvalues[3], pvalues[4], pvalues[5]);
                case 7 -> (String) mh.invoke(pvalues[0], pvalues[1], pvalues[2], pvalues[3], pvalues[4], pvalues[5], pvalues[6]);
                case 8 -> (String) mh.invoke(pvalues[0], pvalues[1], pvalues[2], pvalues[3], pvalues[4], pvalues[5], pvalues[6], pvalues[7]);
                case 9 -> (String) mh.invoke(pvalues[0], pvalues[1], pvalues[2], pvalues[3], pvalues[4], pvalues[5], pvalues[6], pvalues[7], pvalues[8]);
                case 10 -> (String) mh.invoke(pvalues[0], pvalues[1], pvalues[2], pvalues[3], pvalues[4], pvalues[5], pvalues[6], pvalues[7], pvalues[8], pvalues[9]);
                default -> throw new RuntimeException("length too large " + length);
            };
            sum += result.length();
        }
        System.out.println(sum);
    }
}


We use jmap -histo to observe whether the number of hidden classes is growing continuously.

# get pid
jps | grep HiddenClassUnloading

# Count the number of hidden classes
jmap -histo <pid> | grep -c "StringConcat/0"


The result is as follows, the number of hidden classes does not keep growing, so the unloading of hidden classes is working.

➜ jmap -histo 1037 | grep -c "StringConcat/0"
17
➜ jmap -histo 1037 | grep -c "StringConcat/0"
43
➜ jmap -histo 1037 | grep -c "StringConcat/0"
77
➜ jmap -histo 1037 | grep -c "StringConcat/0"
92
➜ jmap -histo 1037 | grep -c "StringConcat/0"
110
➜ jmap -histo 1037 | grep -c "StringConcat/0"
133
➜ jmap -histo 1037 | grep -c "StringConcat/0"
159
➜ jmap -histo 1037 | grep -c "StringConcat/0"
2
➜ jmap -histo 1037 | grep -c "StringConcat/0"

-------------

PR Comment: https://git.openjdk.org/jdk/pull/20273#issuecomment-2277202933


More information about the core-libs-dev mailing list