mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
prepare UI in parallel to appStarter
GitOrigin-RevId: 918a9175475fe2091085bdb7dd0b54a1a49994ca
This commit is contained in:
committed by
intellij-monorepo-bot
parent
a87883bca8
commit
f6ccd9d67c
@@ -1,3 +1,7 @@
|
||||
# 30
|
||||
|
||||
* Add `preloading activity executing`.
|
||||
|
||||
# 29
|
||||
* Add `splash preparation (in queue)` and `splash initialization (in queue)`.
|
||||
* Add `pre app class running`, `repaint manager set`, `linux wm set`. Existing`event queue replacing` doesn't include added metrics anymore.
|
||||
|
||||
@@ -38,7 +38,7 @@ class StartUpPerformanceReporter : StartupActivity, StartUpPerformanceService {
|
||||
companion object {
|
||||
internal val LOG = logger<StartUpMeasurer>()
|
||||
|
||||
internal const val VERSION = "29"
|
||||
internal const val VERSION = "30"
|
||||
|
||||
internal fun sortItems(items: MutableList<ActivityImpl>) {
|
||||
items.sortWith(Comparator { o1, o2 ->
|
||||
|
||||
+1
-2
@@ -57,8 +57,7 @@ final class FileBasedIndexDataInitialization extends IndexDataInitializer<IndexC
|
||||
myRegisteredIndexes = registeredIndexes;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Collection<ThrowableRunnable<?>> initAssociatedDataForExtensions() {
|
||||
private @NotNull Collection<ThrowableRunnable<?>> initAssociatedDataForExtensions() {
|
||||
Activity activity = StartUpMeasurer.startActivity("file index extensions iteration", ActivityCategory.APP_INIT);
|
||||
Iterator<FileBasedIndexExtension<?, ?>> extensions;
|
||||
if (IndexInfrastructure.hasIndices()) {
|
||||
|
||||
+7
-5
@@ -1,12 +1,12 @@
|
||||
// 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.
|
||||
// Copyright 2000-2021 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.ide.customize
|
||||
|
||||
import com.intellij.ide.ApplicationInitializedListener
|
||||
import com.intellij.internal.statistic.eventLog.FeatureUsageData
|
||||
import com.intellij.internal.statistic.service.fus.collectors.FUCounterUsageLogger
|
||||
import com.intellij.internal.statistic.utils.getPluginInfoByDescriptor
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.extensions.PluginDescriptor
|
||||
import java.util.concurrent.ForkJoinPool
|
||||
|
||||
object CustomizeIDEWizardInteractions {
|
||||
var skippedOnPage = -1
|
||||
@@ -36,11 +36,13 @@ data class CustomizeIDEWizardInteraction(
|
||||
val groupId: String?
|
||||
)
|
||||
|
||||
class CustomizeIDEWizardCollectorActivity : ApplicationInitializedListener {
|
||||
internal class CustomizeIDEWizardCollectorActivity : ApplicationInitializedListener {
|
||||
override fun componentsInitialized() {
|
||||
if (CustomizeIDEWizardInteractions.interactions.isEmpty()) return
|
||||
if (CustomizeIDEWizardInteractions.interactions.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
ApplicationManager.getApplication().executeOnPooledThread {
|
||||
ForkJoinPool.commonPool().execute {
|
||||
if (CustomizeIDEWizardInteractions.skippedOnPage != -1) {
|
||||
FUCounterUsageLogger.getInstance().logEvent("customize.wizard", "remaining.pages.skipped",
|
||||
FeatureUsageData().addData("page", CustomizeIDEWizardInteractions.skippedOnPage))
|
||||
|
||||
@@ -16,10 +16,15 @@ import com.intellij.openapi.application.impl.ApplicationImpl
|
||||
import com.intellij.openapi.components.stateStore
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.extensions.ExtensionNotApplicableException
|
||||
import com.intellij.openapi.extensions.PluginDescriptor
|
||||
import com.intellij.openapi.extensions.impl.ExtensionsAreaImpl
|
||||
import com.intellij.openapi.progress.EmptyProgressIndicator
|
||||
import com.intellij.openapi.progress.ProcessCanceledException
|
||||
import com.intellij.openapi.progress.ProgressManager
|
||||
import com.intellij.openapi.progress.util.AbstractProgressIndicatorBase
|
||||
import com.intellij.openapi.progress.util.ProgressIndicatorBase
|
||||
import com.intellij.openapi.ui.DialogEarthquakeShaker
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.IconLoader
|
||||
import com.intellij.openapi.util.SystemInfoRt
|
||||
import com.intellij.openapi.util.SystemPropertyBean
|
||||
@@ -32,7 +37,9 @@ import com.intellij.ui.AppIcon
|
||||
import com.intellij.ui.mac.MacOSApplicationProvider
|
||||
import com.intellij.ui.mac.foundation.Foundation
|
||||
import com.intellij.ui.mac.touchbar.TouchBarsManager
|
||||
import com.intellij.util.TimeoutUtil
|
||||
import com.intellij.util.io.createDirectories
|
||||
import com.intellij.util.io.storage.HeavyProcessLatch
|
||||
import com.intellij.util.lang.ZipFilePool
|
||||
import com.intellij.util.ui.AsyncProcessIcon
|
||||
import net.miginfocom.layout.PlatformDefaults
|
||||
@@ -53,7 +60,6 @@ private val LOG = Logger.getInstance("#com.intellij.idea.ApplicationLoader")
|
||||
private fun executeInitAppInEdt(args: List<String>,
|
||||
initAppActivity: Activity,
|
||||
pluginDescriptorFuture: CompletableFuture<List<IdeaPluginDescriptorImpl>>) {
|
||||
StartupUtil.patchSystem(LOG)
|
||||
val registerComponentFuture = CompletableFuture<List<IdeaPluginDescriptorImpl>>()
|
||||
val app = runActivity("create app") {
|
||||
ApplicationImpl(java.lang.Boolean.getBoolean(PluginManagerCore.IDEA_IS_INTERNAL_PROPERTY), false, Main.isHeadless(),
|
||||
@@ -183,9 +189,7 @@ private fun startApp(app: ApplicationImpl,
|
||||
|
||||
initStoreFuture
|
||||
.thenCompose {
|
||||
// `invokeLater()` is needed to place the app starting code on a freshly minted `IdeEventQueue` instance
|
||||
val placeOnEventQueueActivity = initAppActivity.startChild(Activities.PLACE_ON_EVENT_QUEUE)
|
||||
|
||||
val loadComponentInEdtFuture = CompletableFuture.runAsync({
|
||||
placeOnEventQueueActivity.end()
|
||||
|
||||
@@ -312,7 +316,7 @@ private fun handleExternalCommand(args: List<String>, currentDirectory: String?)
|
||||
return result
|
||||
}
|
||||
|
||||
fun initApplication(rawArgs: List<String>, initUiTask: CompletionStage<*>) {
|
||||
fun initApplication(rawArgs: List<String>, prepareUiFuture: CompletionStage<*>) {
|
||||
val initAppActivity = StartupUtil.startupStart.endAndStart(Activities.INIT_APP)
|
||||
val loadAndInitPluginFuture = CompletableFuture<List<IdeaPluginDescriptorImpl>>()
|
||||
try {
|
||||
@@ -333,7 +337,7 @@ fun initApplication(rawArgs: List<String>, initUiTask: CompletionStage<*>) {
|
||||
}
|
||||
|
||||
// use main thread, avoid thread switching
|
||||
(initUiTask as CompletableFuture<*>).join()
|
||||
(prepareUiFuture as CompletableFuture<*>).join()
|
||||
|
||||
val args = processProgramArguments(rawArgs)
|
||||
EventQueue.invokeLater {
|
||||
@@ -414,6 +418,11 @@ fun callAppInitialized(app: Application): List<RecursiveAction> {
|
||||
}
|
||||
extensionPoint.reset()
|
||||
|
||||
if (!app.isUnitTestMode && !app.isHeadlessEnvironment &&
|
||||
java.lang.Boolean.parseBoolean(System.getProperty("enable.activity.preloading", "true"))) {
|
||||
result.add(Preloader(extensionArea))
|
||||
}
|
||||
|
||||
// should be after scheduling all app initialized listeners (because this activity is not important)
|
||||
result.add(object : RecursiveAction() {
|
||||
override fun compute() {
|
||||
@@ -443,4 +452,85 @@ fun callAppInitialized(app: Application): List<RecursiveAction> {
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private class Preloader(private val extensionArea: ExtensionsAreaImpl) : RecursiveAction() {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
private fun checkHeavyProcessRunning() {
|
||||
if (HeavyProcessLatch.INSTANCE.isRunning) {
|
||||
TimeoutUtil.sleep(1)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
private fun preload(activity: PreloadingActivity, descriptor: PluginDescriptor?) {
|
||||
val indicator = ProgressIndicatorBase()
|
||||
Disposer.register(ApplicationManager.getApplication()) { indicator.cancel() }
|
||||
val wrappingIndicator = object : AbstractProgressIndicatorBase() {
|
||||
override fun checkCanceled() {
|
||||
checkHeavyProcessRunning()
|
||||
indicator.checkCanceled()
|
||||
}
|
||||
|
||||
override fun isCanceled() = indicator.isCanceled
|
||||
}
|
||||
|
||||
if (indicator.isCanceled) {
|
||||
return
|
||||
}
|
||||
checkHeavyProcessRunning()
|
||||
if (indicator.isCanceled) {
|
||||
return
|
||||
}
|
||||
|
||||
val isDebugEnabled = LOG.isDebugEnabled
|
||||
ProgressManager.getInstance().runProcess({
|
||||
val measureActivity = if (descriptor == null) {
|
||||
null
|
||||
}
|
||||
else {
|
||||
StartUpMeasurer.startActivity(activity.javaClass.name,
|
||||
ActivityCategory.PRELOAD_ACTIVITY,
|
||||
descriptor.pluginId.idString)
|
||||
}
|
||||
|
||||
try {
|
||||
activity.preload(wrappingIndicator)
|
||||
}
|
||||
catch (ignore: ProcessCanceledException) {
|
||||
return@runProcess
|
||||
}
|
||||
finally {
|
||||
measureActivity?.end()
|
||||
}
|
||||
if (isDebugEnabled) {
|
||||
LOG.debug("${activity.javaClass.name} finished")
|
||||
}
|
||||
}, indicator)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun compute() {
|
||||
runActivity("preloading activity executing") {
|
||||
val extensionPoint = extensionArea.getExtensionPoint<PreloadingActivity>("com.intellij.preloadingActivity")
|
||||
extensionPoint.processImplementations(/* shouldBeSorted = */ false) { supplier, pluginDescriptor ->
|
||||
val activity: PreloadingActivity
|
||||
try {
|
||||
activity = supplier.get()
|
||||
}
|
||||
catch (ignore: ExtensionNotApplicableException) {
|
||||
return@processImplementations
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
LOG.error(e)
|
||||
return@processImplementations
|
||||
}
|
||||
|
||||
preload(activity, pluginDescriptor)
|
||||
}
|
||||
extensionPoint.reset()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -91,9 +91,9 @@ public final class StartupUtil {
|
||||
private static final String MAGIC_MAC_PATH = "/AppTranslocation/";
|
||||
|
||||
@SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized")
|
||||
private static SocketLock ourSocketLock;
|
||||
private static final AtomicBoolean ourSystemPatched = new AtomicBoolean();
|
||||
private static Future<@Nullable Boolean> ourShellEnvLoaded;
|
||||
private static SocketLock socketLock;
|
||||
private static final AtomicBoolean isLaFForPreStartupSet = new AtomicBoolean();
|
||||
private static Future<@Nullable Boolean> shellEnvLoadFuture;
|
||||
|
||||
private StartupUtil() { }
|
||||
|
||||
@@ -125,8 +125,8 @@ public final class StartupUtil {
|
||||
|
||||
// called by the app after startup
|
||||
public static synchronized void addExternalInstanceListener(@Nullable Function<? super List<String>, ? extends Future<CliResult>> processor) {
|
||||
if (ourSocketLock == null) throw new AssertionError("Not initialized yet");
|
||||
ourSocketLock.setCommandProcessor(processor);
|
||||
if (socketLock == null) throw new AssertionError("Not initialized yet");
|
||||
socketLock.setCommandProcessor(processor);
|
||||
}
|
||||
|
||||
// used externally by TeamCity plugin (as TeamCity cannot use modern API to support old IDE versions)
|
||||
@@ -134,16 +134,16 @@ public final class StartupUtil {
|
||||
@Deprecated
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "2021.3")
|
||||
public static synchronized @Nullable BuiltInServer getServer() {
|
||||
return ourSocketLock == null ? null : ourSocketLock.getServer();
|
||||
return socketLock == null ? null : socketLock.getServer();
|
||||
}
|
||||
|
||||
public static synchronized @NotNull CompletableFuture<BuiltInServer> getServerFuture() {
|
||||
CompletableFuture<BuiltInServer> serverFuture = ourSocketLock == null ? null : ourSocketLock.getServerFuture();
|
||||
CompletableFuture<BuiltInServer> serverFuture = socketLock == null ? null : socketLock.getServerFuture();
|
||||
return serverFuture == null ? CompletableFuture.completedFuture(null) : serverFuture;
|
||||
}
|
||||
|
||||
public static @NotNull Future<@Nullable Boolean> getShellEnvLoadingFuture() {
|
||||
return ourShellEnvLoaded;
|
||||
return shellEnvLoadFuture;
|
||||
}
|
||||
|
||||
private static @Nullable ForkJoinTask<@Nullable Object> loadEuaDocument() {
|
||||
@@ -165,7 +165,7 @@ public final class StartupUtil {
|
||||
|
||||
public interface AppStarter {
|
||||
/* called from IDE init thread */
|
||||
void start(@NotNull List<String> args, @NotNull CompletionStage<?> initUiTask);
|
||||
void start(@NotNull List<String> args, @NotNull CompletionStage<?> prepareUiFuture);
|
||||
|
||||
/* called from IDE init thread */
|
||||
default void beforeImportConfigs() {}
|
||||
@@ -284,7 +284,7 @@ public final class StartupUtil {
|
||||
});
|
||||
|
||||
// don't load EnvironmentUtil class in main thread
|
||||
ourShellEnvLoaded = ForkJoinPool.commonPool().submit(() -> {
|
||||
shellEnvLoadFuture = ForkJoinPool.commonPool().submit(() -> {
|
||||
Activity subActivity = StartUpMeasurer.startActivity("environment loading", ActivityCategory.APP_INIT);
|
||||
Path envReaderFile = PathManager.findBinFile(EnvironmentUtil.READER_FILE_NAME);
|
||||
return envReaderFile == null ? null : EnvironmentUtil.loadEnvironment(envReaderFile, subActivity);
|
||||
@@ -298,7 +298,23 @@ public final class StartupUtil {
|
||||
runPreAppClass(log);
|
||||
}
|
||||
|
||||
startApp(Arrays.asList(args), initUiTask, log, configImportNeeded, appStarterFuture, euaDocument);
|
||||
CompletableFuture<@Nullable Void> prepareUiFuture = new CompletableFuture<>();
|
||||
initUiTask.thenRun(() -> {
|
||||
// called in EDT, but other events in queue should be processed before patchSystem
|
||||
EventQueue.invokeLater(() -> {
|
||||
try {
|
||||
patchSystem(log);
|
||||
}
|
||||
catch (Throwable e) {
|
||||
prepareUiFuture.completeExceptionally(e);
|
||||
StartupAbortedException.processException(e);
|
||||
return;
|
||||
}
|
||||
|
||||
prepareUiFuture.complete(null);
|
||||
});
|
||||
});
|
||||
startApp(Arrays.asList(args), prepareUiFuture, log, configImportNeeded, appStarterFuture, euaDocument);
|
||||
}
|
||||
|
||||
private static @NotNull AppStarter getAppStarter(@NotNull ForkJoinTask<AppStarter> mainStartFuture) {
|
||||
@@ -311,7 +327,7 @@ public final class StartupUtil {
|
||||
}
|
||||
|
||||
private static void startApp(@NotNull List<String> args,
|
||||
@NotNull CompletableFuture<?> initUiTask,
|
||||
@NotNull CompletableFuture<?> prepareUiFuture,
|
||||
@NotNull Logger log,
|
||||
boolean configImportNeeded,
|
||||
@NotNull ForkJoinTask<AppStarter> appStarterFuture,
|
||||
@@ -319,11 +335,12 @@ public final class StartupUtil {
|
||||
if (!Main.isHeadless()) {
|
||||
Activity activity = StartUpMeasurer.startMainActivity("eua showing");
|
||||
Object document = euaDocument == null ? null : euaDocument.join();
|
||||
boolean agreementDialogWasShown = document != null && showUserAgreementAndConsentsIfNeeded(log, initUiTask, (EndUserAgreement.Document)document);
|
||||
boolean agreementDialogWasShown = document != null &&
|
||||
showUserAgreementAndConsentsIfNeeded(log, prepareUiFuture, (EndUserAgreement.Document)document);
|
||||
|
||||
if (configImportNeeded) {
|
||||
activity = activity.endAndStart("screen reader checking");
|
||||
runInEdtAndWait(log, AccessibilityUtils::enableScreenReaderSupportIfNecessary, initUiTask);
|
||||
runInEdtAndWait(log, AccessibilityUtils::enableScreenReaderSupportIfNecessary, prepareUiFuture);
|
||||
}
|
||||
|
||||
if (configImportNeeded) {
|
||||
@@ -331,7 +348,7 @@ public final class StartupUtil {
|
||||
AppStarter appStarter = getAppStarter(appStarterFuture);
|
||||
appStarter.beforeImportConfigs();
|
||||
Path newConfigDir = PathManager.getConfigDir();
|
||||
runInEdtAndWait(log, () -> ConfigImportHelper.importConfigsTo(agreementDialogWasShown, newConfigDir, args, log), initUiTask);
|
||||
runInEdtAndWait(log, () -> ConfigImportHelper.importConfigsTo(agreementDialogWasShown, newConfigDir, args, log), prepareUiFuture);
|
||||
appStarter.importFinished(newConfigDir);
|
||||
|
||||
if (!ConfigImportHelper.isConfigImported()) {
|
||||
@@ -349,13 +366,13 @@ public final class StartupUtil {
|
||||
EdtInvocationManager.SwingEdtInvocationManager edtInvocationManager = new EdtInvocationManager.SwingEdtInvocationManager() {
|
||||
@Override
|
||||
public void invokeAndWait(@NotNull Runnable task) {
|
||||
runInEdtAndWait(log, task, initUiTask);
|
||||
runInEdtAndWait(log, task, prepareUiFuture);
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
oldEdtInvocationManager = EdtInvocationManager.setEdtInvocationManager(edtInvocationManager);
|
||||
getAppStarter(appStarterFuture).start(args, initUiTask);
|
||||
getAppStarter(appStarterFuture).start(args, prepareUiFuture);
|
||||
}
|
||||
finally {
|
||||
EdtInvocationManager.restoreEdtInvocationManager(edtInvocationManager, oldEdtInvocationManager);
|
||||
@@ -471,7 +488,7 @@ public final class StartupUtil {
|
||||
private static void showSplashIfNeeded(@NotNull String @NotNull [] args,
|
||||
@Nullable ForkJoinTask<@Nullable Object> eulaDocument,
|
||||
@NotNull Activity activity) {
|
||||
// product specifies `slash` VM properties, `nosplash` is deprecated property, it should be checked first
|
||||
// product specifies `splash` VM properties, `nosplash` is deprecated property, it should be checked first
|
||||
if (Boolean.getBoolean(CommandLineArgs.NO_SPLASH) || !Boolean.getBoolean(CommandLineArgs.SPLASH) || Main.isLightEdit()) {
|
||||
return;
|
||||
}
|
||||
@@ -643,19 +660,19 @@ public final class StartupUtil {
|
||||
}
|
||||
|
||||
private static void lockSystemDirs(@NotNull Path configPath, @NotNull Path systemPath, @NotNull String @NotNull[] args) throws Exception {
|
||||
if (ourSocketLock != null) {
|
||||
if (socketLock != null) {
|
||||
throw new AssertionError("Already initialized");
|
||||
}
|
||||
ourSocketLock = new SocketLock(configPath, systemPath);
|
||||
socketLock = new SocketLock(configPath, systemPath);
|
||||
|
||||
Map.Entry<SocketLock.ActivationStatus, CliResult> status = ourSocketLock.lockAndTryActivate(args);
|
||||
Map.Entry<SocketLock.ActivationStatus, CliResult> status = socketLock.lockAndTryActivate(args);
|
||||
switch (status.getKey()) {
|
||||
case NO_INSTANCE: {
|
||||
ShutDownTracker.getInstance().registerShutdownTask(() -> {
|
||||
//noinspection SynchronizeOnThis
|
||||
synchronized (StartupUtil.class) {
|
||||
ourSocketLock.dispose();
|
||||
ourSocketLock = null;
|
||||
socketLock.dispose();
|
||||
socketLock = null;
|
||||
}
|
||||
});
|
||||
break;
|
||||
@@ -844,9 +861,9 @@ public final class StartupUtil {
|
||||
}
|
||||
|
||||
// must be called from EDT
|
||||
public static boolean patchSystem(@NotNull Logger log) throws Throwable {
|
||||
if (!ourSystemPatched.compareAndSet(false, true)) {
|
||||
return false;
|
||||
private static void patchSystem(@NotNull Logger log) throws Throwable {
|
||||
if (!isLaFForPreStartupSet.compareAndSet(false, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Activity activity = StartUpMeasurer.startActivity("event queue replacing", ActivityCategory.APP_INIT);
|
||||
@@ -873,46 +890,38 @@ public final class StartupUtil {
|
||||
IconManager.activate(new CoreIconManager());
|
||||
}
|
||||
activity.end();
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean showUserAgreementAndConsentsIfNeeded(@NotNull Logger log,
|
||||
@NotNull CompletableFuture<?> initUiTask,
|
||||
@NotNull CompletableFuture<?> prepareUiFuture,
|
||||
@NotNull EndUserAgreement.Document agreement) {
|
||||
boolean dialogWasShown = false;
|
||||
EndUserAgreement.updateCachedContentToLatestBundledVersion();
|
||||
if (!agreement.isAccepted()) {
|
||||
// todo: does not seem to request focus when shown
|
||||
runInEdtAndWait(log, () -> Agreements.INSTANCE.showEndUserAndDataSharingAgreements(agreement), initUiTask);
|
||||
runInEdtAndWait(log, () -> Agreements.INSTANCE.showEndUserAndDataSharingAgreements(agreement), prepareUiFuture);
|
||||
dialogWasShown = true;
|
||||
}
|
||||
else if (ConsentOptions.getInstance().getConsents().getValue()) {
|
||||
runInEdtAndWait(log, Agreements.INSTANCE::showDataSharingAgreement, initUiTask);
|
||||
runInEdtAndWait(log, Agreements.INSTANCE::showDataSharingAgreement, prepareUiFuture);
|
||||
}
|
||||
return dialogWasShown;
|
||||
}
|
||||
|
||||
private static void runInEdtAndWait(@NotNull Logger log, @NotNull Runnable runnable, @NotNull CompletableFuture<?> initUiTask) {
|
||||
initUiTask.join();
|
||||
private static void runInEdtAndWait(@NotNull Logger log, @NotNull Runnable runnable, @NotNull CompletableFuture<?> prepareUiFuture) {
|
||||
prepareUiFuture.join();
|
||||
try {
|
||||
if (!ourSystemPatched.get()) {
|
||||
EventQueue.invokeAndWait(() -> {
|
||||
EventQueue.invokeAndWait(() -> {
|
||||
if (!isLaFForPreStartupSet.get()) {
|
||||
try {
|
||||
if (!patchSystem(log)) {
|
||||
return;
|
||||
}
|
||||
|
||||
UIManager.setLookAndFeel(IntelliJLaf.class.getName());
|
||||
// we don't set AppUIUtil.updateForDarcula(false) because light is default
|
||||
}
|
||||
catch (Throwable e) {
|
||||
log.warn(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// this invokeAndWait() call is needed to place on a freshly minted IdeEventQueue instance
|
||||
EventQueue.invokeAndWait(runnable);
|
||||
}
|
||||
runnable.run();
|
||||
});
|
||||
}
|
||||
catch (InterruptedException | InvocationTargetException e) {
|
||||
log.warn(e);
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
// Copyright 2000-2021 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;
|
||||
|
||||
import com.intellij.diagnostic.Activity;
|
||||
import com.intellij.diagnostic.ActivityCategory;
|
||||
import com.intellij.diagnostic.StartUpMeasurer;
|
||||
import com.intellij.ide.ApplicationInitializedListener;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.extensions.PluginDescriptor;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.util.AbstractProgressIndicatorBase;
|
||||
import com.intellij.openapi.progress.util.ProgressIndicatorBase;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.util.TimeoutUtil;
|
||||
import com.intellij.util.concurrency.AppExecutorUtil;
|
||||
import com.intellij.util.io.storage.HeavyProcessLatch;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
final class Preloader implements ApplicationInitializedListener {
|
||||
private static final Logger LOG = Logger.getInstance(Preloader.class);
|
||||
|
||||
private static void checkHeavyProcessRunning() {
|
||||
if (HeavyProcessLatch.INSTANCE.isRunning()) {
|
||||
TimeoutUtil.sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentsInitialized() {
|
||||
Application app = ApplicationManager.getApplication();
|
||||
if (app.isUnitTestMode() || app.isHeadlessEnvironment() ||
|
||||
!Boolean.parseBoolean(System.getProperty("enable.activity.preloading", "true"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
new ExtensionPointName<PreloadingActivity>("com.intellij.preloadingActivity").processWithPluginDescriptor(Preloader::preload);
|
||||
}
|
||||
|
||||
private static void preload(@NotNull PreloadingActivity activity, @Nullable PluginDescriptor descriptor) {
|
||||
ExecutorService executor = AppExecutorUtil.createBoundedApplicationPoolExecutor("Preloader Pool", 1, false);
|
||||
|
||||
ProgressIndicator indicator = new ProgressIndicatorBase();
|
||||
Disposer.register(ApplicationManager.getApplication(), indicator::cancel);
|
||||
ProgressIndicator wrappingIndicator = new AbstractProgressIndicatorBase() {
|
||||
@Override
|
||||
public void checkCanceled() {
|
||||
checkHeavyProcessRunning();
|
||||
indicator.checkCanceled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCanceled() {
|
||||
return indicator.isCanceled();
|
||||
}
|
||||
};
|
||||
|
||||
executor.execute(() -> {
|
||||
if (indicator.isCanceled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
checkHeavyProcessRunning();
|
||||
if (indicator.isCanceled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ProgressManager.getInstance().runProcess(() -> {
|
||||
Activity measureActivity;
|
||||
if (descriptor == null) {
|
||||
measureActivity = null;
|
||||
}
|
||||
else {
|
||||
measureActivity = StartUpMeasurer.startActivity(activity.getClass().getName(), ActivityCategory.PRELOAD_ACTIVITY, descriptor.getPluginId().getIdString());
|
||||
}
|
||||
|
||||
try {
|
||||
activity.preload(wrappingIndicator);
|
||||
}
|
||||
catch (ProcessCanceledException ignore) {
|
||||
return;
|
||||
}
|
||||
finally {
|
||||
if (measureActivity != null) {
|
||||
measureActivity.end();
|
||||
}
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug(activity.getClass().getName() + " finished");
|
||||
}
|
||||
}, indicator);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import com.intellij.openapi.application.ex.ApplicationManagerEx;
|
||||
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.VirtualMachine;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import sun.tools.attach.HotSpotVirtualMachine;
|
||||
@@ -60,7 +59,7 @@ final class JitSuppressor implements ApplicationInitializedListener {
|
||||
|
||||
@Override
|
||||
public void componentsInitialized() {
|
||||
if (!SystemProperties.getBooleanProperty("enable.jit.suppressor", false)) {
|
||||
if (!Boolean.getBoolean("enable.jit.suppressor")) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2020 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.
|
||||
// Copyright 2000-2021 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.idea;
|
||||
|
||||
import com.intellij.ide.customize.CustomizeIDEWizardStepsProvider;
|
||||
@@ -15,8 +15,8 @@ public final class MainImpl implements StartupUtil.AppStarter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(@NotNull List<String> args, @NotNull CompletionStage<?> initUiTask) {
|
||||
ApplicationLoader.initApplication(args, initUiTask);
|
||||
public void start(@NotNull List<String> args, @NotNull CompletionStage<?> prepareUiFuture) {
|
||||
ApplicationLoader.initApplication(args, prepareUiFuture);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -731,7 +731,6 @@
|
||||
<statistics.collectorExtension implementation="com.intellij.ide.actions.ToolwindowFusEventFields"/>
|
||||
<statistics.collectorExtension implementation="com.intellij.ide.actions.DragEditorTabsFusEventFields"/>
|
||||
|
||||
<applicationInitializedListener implementation="com.intellij.openapi.application.Preloader"/>
|
||||
<applicationInitializedListener implementation="com.intellij.ide.customize.CustomizeIDEWizardCollectorActivity"/>
|
||||
|
||||
<statistics.applicationUsagesCollector implementation="com.intellij.featureStatistics.fusCollectors.EAPUsageCollector"/>
|
||||
|
||||
Reference in New Issue
Block a user