From c9fe57714a7f766a0b75841db1463e9c3b7e06cf Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 15 Jul 2019 10:56:30 +0200 Subject: [PATCH] add JitSuppressor (disabled for now) to help with IDEA-207243 High CPU Usage while typing ( goes over 300%) GitOrigin-RevId: 25ead0064d0405b564bdf212c586024db4e3da6a --- .../build/impl/VmOptionsGenerator.groovy | 2 +- .../application/impl/JitSuppressor.java | 113 ++++++++++++++++++ .../src/componentSets/Platform.xml | 3 + 3 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 platform/platform-impl/src/com/intellij/openapi/application/impl/JitSuppressor.java diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/VmOptionsGenerator.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/VmOptionsGenerator.groovy index b759cbdba408..447555ce6074 100644 --- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/VmOptionsGenerator.groovy +++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/VmOptionsGenerator.groovy @@ -33,7 +33,7 @@ class VmOptionsGenerator { '-Djdk.http.auth.tunneling.disabledSchemes=""', '-XX:+HeapDumpOnOutOfMemoryError', '-XX:-OmitStackTraceInFastThrow', - '-Djdk.attach.allowAttachSelf', + '-Djdk.attach.allowAttachSelf=true', ] static String computeVmOptions(JvmArchitecture arch, boolean isEAP, ProductProperties productProperties) { diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/JitSuppressor.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/JitSuppressor.java new file mode 100644 index 000000000000..738fd1147aa7 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/JitSuppressor.java @@ -0,0 +1,113 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.openapi.application.impl; + +import com.intellij.execution.process.OSProcessUtil; +import com.intellij.ide.PowerSaveMode; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.SystemProperties; +import com.sun.tools.attach.AttachNotSupportedException; +import com.sun.tools.attach.VirtualMachine; +import sun.tools.attach.HotSpotVirtualMachine; + +import java.io.File; +import java.io.IOException; + +// NOTE: compile with --add-exports jdk.attach/sun.tools.attach=ALL-UNNAMED in module-aware jdk +public class JitSuppressor implements PowerSaveMode.Listener { + private static final Logger LOG = Logger.getInstance(JitSuppressor.class); + private static final String SELF_ATTACH_PROP = "jdk.attach.allowAttachSelf"; + private static final String EXCLUDE_ALL_FROM_C2_CLAUSE = "{ match : [\"*.*\"], c2 : { Exclude : true }}"; + // Limit C2 compilation with the given packages only. The package set was computed by test performance analysis: + // it makes performance tests timing comparable with full C2 and same time IDE does not load CPU heavily with this limitation. + private static final String[] C2_LIMIT_MASKS = { + "com/intellij/openapi/application/*.*", + "com/intellij/openapi/editor/*.*", + "com/intellij/openapi/project/*.*", + "com/intellij/openapi/util/text/*.*", + "com/intellij/openapi/vfs/*.*", + "com/intellij/openapi/fileTypes/*.*", + "com/intellij/psi/codeStyle/*.*", + "com/intellij/psi/util/*.*", + "com/intellij/util/*.*", + "java/lang/*.*", + "java/math/*.*", + "sun/*.*", + }; + + public JitSuppressor() { + if (!SystemProperties.getBooleanProperty("enable.jit.suppressor", false)) { + return; + } + + // java.specification.version has values "1.8", "1.7" e.t.c. for jdk <= 8 and "9", "10", "11", 12" for others + if (System.getProperty("java.specification.version").contains(".")) return; + + String javaSpecVendor = System.getProperty("java.vm.specification.vendor"); + if (!"Oracle Corporation".equals(javaSpecVendor)) { + LOG.warn("JitSuppressor functionality is not supported on non-Oracle vm. This one is " + javaSpecVendor); + return; + } + + if (!"true".equals(System.getProperty(SELF_ATTACH_PROP))) { + String msg = "JitSuppressor wasn't registered. Please ensure the command line contains -D" + SELF_ATTACH_PROP + "=true"; + if (ApplicationInfoImpl.isInStressTest()) { + LOG.warn(msg + " to get production-like performance"); + } + else if (!ApplicationManager.getApplication().isUnitTestMode()) { + LOG.warn(msg); + } + return; + } + + LOG.info("JitSuppressor is active"); + + ApplicationManager.getApplication().getMessageBus().connect().subscribe(PowerSaveMode.TOPIC, this); + + // call the handler to make initial setup + powerSaveStateChanged(); + } + + @Override + public void powerSaveStateChanged() { + String directives = generateDirectives(); + + Runnable runnable = () -> setDirectives(directives); + if (ApplicationManager.getApplication().isUnitTestMode()) { + runnable.run(); + } else { + ApplicationManager.getApplication().executeOnPooledThread(runnable); + } + } + + private static void setDirectives(String directives) { + File tmpFile = null; + try { + tmpFile = FileUtil.createTempFile("c2_directive", "json"); + FileUtil.writeToFile(tmpFile, directives); + + VirtualMachine vm = VirtualMachine.attach(OSProcessUtil.getApplicationPid()); + HotSpotVirtualMachine hvm = (HotSpotVirtualMachine)vm; + hvm.executeJCmd("Compiler.directives_clear"); + hvm.executeJCmd("Compiler.directives_add " + tmpFile.getAbsolutePath()); + vm.detach(); + } + catch (AttachNotSupportedException | IOException e) { + LOG.error(e); + } + finally { + if (tmpFile != null) { + FileUtil.delete(tmpFile); + } + } + } + + private static String generateDirectives() { + String includes = PowerSaveMode.isEnabled() + ? "" + : StringUtil.join(C2_LIMIT_MASKS, mask -> "{ match: [\"" + mask + "\"], c2: { Exclude: false, }, },", ""); + return "[" + includes + EXCLUDE_ALL_FROM_C2_CLAUSE + "]"; + } +} diff --git a/platform/platform-resources/src/componentSets/Platform.xml b/platform/platform-resources/src/componentSets/Platform.xml index c5dc56508444..f3822b6268a9 100644 --- a/platform/platform-resources/src/componentSets/Platform.xml +++ b/platform/platform-resources/src/componentSets/Platform.xml @@ -59,6 +59,9 @@ com.intellij.diagnostic.PerformanceWatcher + + com.intellij.openapi.application.impl.JitSuppressor + com.intellij.notification.NotificationsConfiguration