MemoryUsageBenchmark.java revision 13017:134219a5b0ec
1/*
2 * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23package org.graalvm.compiler.hotspot.test;
24
25import static org.graalvm.compiler.debug.internal.MemUseTrackerImpl.getCurrentThreadAllocatedBytes;
26
27import org.graalvm.compiler.api.test.Graal;
28import org.graalvm.compiler.core.test.AllocSpy;
29import org.graalvm.compiler.debug.DebugEnvironment;
30import org.graalvm.compiler.hotspot.CompilationTask;
31import org.graalvm.compiler.hotspot.HotSpotGraalCompiler;
32import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
33import org.graalvm.compiler.options.OptionValues;
34
35import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
36import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
37import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider;
38import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
39import jdk.vm.ci.runtime.JVMCICompiler;
40
41/**
42 * Used to benchmark memory usage during Graal compilation.
43 *
44 * To benchmark:
45 *
46 * <pre>
47 *     mx vm -XX:-UseJVMCIClassLoader -cp @org.graalvm.compiler.hotspot.test org.graalvm.compiler.hotspot.test.MemoryUsageBenchmark
48 * </pre>
49 *
50 * Memory analysis for a {@link CompileTheWorld} execution can also be performed. For example:
51 *
52 * <pre>
53 *     mx vm -XX:-UseJVMCIClassLoader -DCompileTheWorld.Classpath=$HOME/SPECjvm2008/SPECjvm2008.jar -cp @org.graalvm.compiler.hotspot.test org.graalvm.compiler.hotspot.test.MemoryUsageBenchmark
54 * </pre>
55 */
56public class MemoryUsageBenchmark extends HotSpotGraalCompilerTest {
57
58    public static int simple(int a, int b) {
59        return a + b;
60    }
61
62    public static synchronized int complex(CharSequence cs) {
63        if (cs instanceof String) {
64            return cs.hashCode();
65        }
66
67        if (cs instanceof StringBuilder) {
68            int[] hash = {0};
69            cs.chars().forEach(c -> hash[0] += c);
70            return hash[0];
71        }
72
73        int res = 0;
74
75        // Exercise lock elimination
76        synchronized (cs) {
77            res = cs.length();
78        }
79        synchronized (cs) {
80            res = cs.hashCode() ^ 31;
81        }
82
83        for (int i = 0; i < cs.length(); i++) {
84            res *= cs.charAt(i);
85        }
86
87        // A fixed length loop with some canonicalizable arithmetics will
88        // activate loop unrolling and more canonicalization
89        int sum = 0;
90        for (int i = 0; i < 5; i++) {
91            sum += i * 2;
92        }
93        res += sum;
94
95        // Activates escape-analysis
96        res += new String("asdf").length();
97
98        return res;
99    }
100
101    static class MemoryUsageCloseable implements AutoCloseable {
102
103        private final long start;
104        private final String name;
105
106        MemoryUsageCloseable(String name) {
107            this.name = name;
108            this.start = getCurrentThreadAllocatedBytes();
109        }
110
111        @Override
112        public void close() {
113            long end = getCurrentThreadAllocatedBytes();
114            long allocated = end - start;
115            System.out.println(name + ": " + allocated);
116        }
117    }
118
119    public static void main(String[] args) {
120        // Ensure a Graal runtime is initialized prior to Debug being initialized as the former
121        // may include processing command line options used by the latter.
122        Graal.getRuntime();
123
124        // Ensure a debug configuration for this thread is initialized
125        DebugEnvironment.ensureInitialized(getInitialOptions());
126        new MemoryUsageBenchmark().run();
127    }
128
129    @SuppressWarnings("try")
130    private void doCompilation(String methodName, String label) {
131        HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(methodName);
132
133        // invalidate any existing compiled code
134        method.reprofile();
135
136        long jvmciEnv = 0L;
137
138        try (MemoryUsageCloseable c = label == null ? null : new MemoryUsageCloseable(label)) {
139            HotSpotJVMCIRuntimeProvider runtime = HotSpotJVMCIRuntime.runtime();
140            int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI;
141            HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, jvmciEnv);
142            CompilationTask task = new CompilationTask(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), request, true, false, getInitialOptions());
143            task.runCompilation();
144        }
145    }
146
147    @SuppressWarnings("try")
148    private void allocSpyCompilation(String methodName) {
149        if (AllocSpy.isEnabled()) {
150            HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(methodName);
151
152            // invalidate any existing compiled code
153            method.reprofile();
154
155            long jvmciEnv = 0L;
156            try (AllocSpy as = AllocSpy.open(methodName)) {
157                HotSpotJVMCIRuntimeProvider runtime = HotSpotJVMCIRuntime.runtime();
158                HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, JVMCICompiler.INVOCATION_ENTRY_BCI, jvmciEnv);
159                CompilationTask task = new CompilationTask(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), request, true, false, getInitialOptions());
160                task.runCompilation();
161            }
162        }
163    }
164
165    private static final boolean verbose = Boolean.getBoolean("verbose");
166
167    private void compileAndTime(String methodName) {
168
169        // Parse in eager mode to resolve methods/fields/classes
170        parseEager(methodName, AllowAssumptions.YES);
171
172        // Warm up and initialize compiler phases used by this compilation
173        for (int i = 0; i < 10; i++) {
174            doCompilation(methodName, verbose ? methodName + "[warmup-" + i + "]" : null);
175        }
176
177        doCompilation(methodName, methodName);
178    }
179
180    public void run() {
181        compileAndTime("simple");
182        compileAndTime("complex");
183        OptionValues options = CompileTheWorld.loadOptions(getInitialOptions());
184        if (CompileTheWorld.Options.Classpath.getValue(options) != CompileTheWorld.SUN_BOOT_CLASS_PATH) {
185            HotSpotJVMCIRuntimeProvider runtime = HotSpotJVMCIRuntime.runtime();
186            CompileTheWorld ctw = new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), options);
187            try {
188                ctw.compile();
189            } catch (Throwable e) {
190                e.printStackTrace();
191            }
192        }
193        allocSpyCompilation("simple");
194        allocSpyCompilation("complex");
195    }
196}
197