From 397d507ada822e9b483b26fd045a3526527992f4 Mon Sep 17 00:00:00 2001 From: Michael Bien Date: Wed, 17 Jul 2024 15:53:52 +0200 Subject: [PATCH] Warmup Maven Embedder to improve first-project-creation UX performance: - first embedder initialization can take a while, async-profiler showed that a big chunk of it is spent within google guice - this starts the warmup task early, which solves the problem, since this will happen while the user is looking at the wizard - the warmup task is a no-op if it was already initialized cleanup: - small jdk 17 renovation --- .../nbproject/project.properties | 2 +- .../maven/embedder/DependencyTreeFactory.java | 4 +- .../maven/embedder/EmbedderConfiguration.java | 27 ++---- .../maven/embedder/EmbedderFactory.java | 95 +++++++++---------- .../modules/maven/embedder/MavenEmbedder.java | 10 +- .../embedder/NBRepositoryModelResolver.java | 9 +- 6 files changed, 61 insertions(+), 86 deletions(-) diff --git a/java/maven.embedder/nbproject/project.properties b/java/maven.embedder/nbproject/project.properties index bb898d782a35..9ffd2ba29fcc 100644 --- a/java/maven.embedder/nbproject/project.properties +++ b/java/maven.embedder/nbproject/project.properties @@ -16,7 +16,7 @@ # under the License. is.autoload=true -javac.source=1.8 +javac.release=17 javac.compilerargs=-Xlint -Xlint:-serial release.external/jdom2-2.0.6.1.jar=modules/ext/maven/jdom2-2.0.6.1.jar release.external/maven-dependency-tree-2.2.jar=modules/ext/maven/maven-dependency-tree-2.2.jar diff --git a/java/maven.embedder/src/org/netbeans/modules/maven/embedder/DependencyTreeFactory.java b/java/maven.embedder/src/org/netbeans/modules/maven/embedder/DependencyTreeFactory.java index be01e6e54490..01251a25e088 100644 --- a/java/maven.embedder/src/org/netbeans/modules/maven/embedder/DependencyTreeFactory.java +++ b/java/maven.embedder/src/org/netbeans/modules/maven/embedder/DependencyTreeFactory.java @@ -19,7 +19,7 @@ package org.netbeans.modules.maven.embedder; import java.util.Collection; -import java.util.Collections; +import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.maven.MavenExecutionException; @@ -45,7 +45,7 @@ public class DependencyTreeFactory { @Deprecated public static DependencyNode createDependencyTree(MavenProject project, MavenEmbedder embedder, String scope) { try { - return createDependencyTree(project, embedder, Collections.singleton(scope)); + return createDependencyTree(project, embedder, List.of(scope)); } catch (MavenExecutionException ex) { LOG.log(Level.INFO, "Dependency tree scan failed", ex); return null; diff --git a/java/maven.embedder/src/org/netbeans/modules/maven/embedder/EmbedderConfiguration.java b/java/maven.embedder/src/org/netbeans/modules/maven/embedder/EmbedderConfiguration.java index 07208d8d068b..19f2f2d4da18 100644 --- a/java/maven.embedder/src/org/netbeans/modules/maven/embedder/EmbedderConfiguration.java +++ b/java/maven.embedder/src/org/netbeans/modules/maven/embedder/EmbedderConfiguration.java @@ -27,39 +27,26 @@ * * @author mkleint */ -class EmbedderConfiguration { - private final PlexusContainer cont; - private final Properties props; - private final boolean offline; - private final File settingsXml; - private final Properties userprops; - - EmbedderConfiguration(PlexusContainer cont, Properties props, Properties userprops, boolean offline, File settingsXml) { - this.cont = cont; - this.props = props; - this.offline = offline; - this.settingsXml = settingsXml; - this.userprops = userprops; - } +record EmbedderConfiguration(PlexusContainer container, Properties systemProps, Properties userProps, boolean offline, File settingsXml) { Properties getSystemProperties() { - return props; + return systemProps(); } - + Properties getUserProperties() { - return userprops; + return userProps(); } PlexusContainer getContainer() { - return cont; + return container(); } public boolean isOffline() { - return offline; + return offline(); } File getSettingsXml() { - return settingsXml; + return settingsXml(); } } diff --git a/java/maven.embedder/src/org/netbeans/modules/maven/embedder/EmbedderFactory.java b/java/maven.embedder/src/org/netbeans/modules/maven/embedder/EmbedderFactory.java index 88e1d2d10591..752f59fd4ae2 100644 --- a/java/maven.embedder/src/org/netbeans/modules/maven/embedder/EmbedderFactory.java +++ b/java/maven.embedder/src/org/netbeans/modules/maven/embedder/EmbedderFactory.java @@ -60,35 +60,33 @@ public final class EmbedderFactory { //same prop constant in MavenSettings.java static final String PROP_DEFAULT_OPTIONS = "defaultOptions"; - private static final Set forbidden = new HashSet(); - static { - forbidden.add("netbeans.logger.console"); //NOI18N - forbidden.add("java.util.logging.config.class"); //NOI18N - forbidden.add("netbeans.autoupdate.language"); //NOI18N - forbidden.add("netbeans.dirs"); //NOI18N - forbidden.add("netbeans.home"); //NOI18N - forbidden.add("sun.awt.exception.handler"); //NOI18N - forbidden.add("org.openide.TopManager.GUI"); //NOI18N - forbidden.add("org.openide.major.version"); //NOI18N - forbidden.add("netbeans.autoupdate.variant"); //NOI18N - forbidden.add("netbeans.dynamic.classpath"); //NOI18N - forbidden.add("netbeans.autoupdate.country"); //NOI18N - forbidden.add("netbeans.hash.code"); //NOI18N - forbidden.add("org.openide.TopManager"); //NOI18N - forbidden.add("org.openide.version"); //NOI18N - forbidden.add("netbeans.buildnumber"); //NOI18N - forbidden.add("javax.xml.parsers.DocumentBuilderFactory"); //NOI18N - forbidden.add("javax.xml.parsers.SAXParserFactory"); //NOI18N - forbidden.add("rave.build"); //NOI18N - forbidden.add("netbeans.accept_license_class"); //NOI18N - forbidden.add("rave.version"); //NOI18N - forbidden.add("netbeans.autoupdate.version"); //NOI18N - forbidden.add("netbeans.importclass"); //NOI18N - forbidden.add("netbeans.user"); //NOI18N -// forbidden.add("java.class.path"); -// forbidden.add("https.nonProxyHosts"); - - } + private static final Set forbidden = Set.of( + "netbeans.logger.console", //NOI18N + "java.util.logging.config.class", //NOI18N + "netbeans.autoupdate.language", //NOI18N + "netbeans.dirs", //NOI18N + "netbeans.home", //NOI18N + "sun.awt.exception.handler", //NOI18N + "org.openide.TopManager.GUI", //NOI18N + "org.openide.major.version", //NOI18N + "netbeans.autoupdate.variant", //NOI18N + "netbeans.dynamic.classpath", //NOI18N + "netbeans.autoupdate.country", //NOI18N + "netbeans.hash.code", //NOI18N + "org.openide.TopManager", //NOI18N + "org.openide.version", //NOI18N + "netbeans.buildnumber", //NOI18N + "javax.xml.parsers.DocumentBuilderFactory", //NOI18N + "javax.xml.parsers.SAXParserFactory", //NOI18N + "rave.build", //NOI18N + "netbeans.accept_license_class", //NOI18N + "rave.version", //NOI18N + "netbeans.autoupdate.version", //NOI18N + "netbeans.importclass", //NOI18N + "netbeans.user" //NOI18N +// "java.class.path", +// "https.nonProxyHosts" + ); private static final Logger LOG = Logger.getLogger(EmbedderFactory.class.getName()); @@ -100,31 +98,24 @@ public final class EmbedderFactory { private static final RequestProcessor RP = new RequestProcessor("Maven Embedder warmup"); - private static final RequestProcessor.Task warmupTask = RP.create(new Runnable() { - @Override - public void run() { - //#211158 after being reset, recreate the instance for followup usage. - //makes the performance stats of the project embedder after resetting more predictable - getProjectEmbedder(); - } - }); + //#211158 after being reset, recreate the instance for followup usage. + //makes the performance stats of the project embedder after resetting more predictable + private static final RequestProcessor.Task warmupTask = RP.create(EmbedderFactory::getProjectEmbedder); static { - RP.post(new Runnable() { - @Override - public void run() { //#228379 - OpenProjects.getDefault().addProjectGroupChangeListener(new ProjectGroupChangeListener() { - @Override - public void projectGroupChanging(ProjectGroupChangeEvent event) { - resetCachedEmbedders(); - } - - @Override - public void projectGroupChanged(ProjectGroupChangeEvent event) { - } - }); - } + RP.post(() -> { //#228379 + OpenProjects.getDefault().addProjectGroupChangeListener(new ProjectGroupChangeListener() { + @Override + public void projectGroupChanging(ProjectGroupChangeEvent event) { + resetCachedEmbedders(); + } + @Override + public void projectGroupChanged(ProjectGroupChangeEvent event) {} + }); }); + // start initialization; guice can take a while the first time it runs + // if something calls getProjectEmbedder() in the mean time, this is becomes a no-op + warmupTask.schedule(100); } private EmbedderFactory() { @@ -236,7 +227,7 @@ public static void setGroupedMavenHome(ProjectGroup grp, File path) { static Map getCustomGlobalUserProperties() { //maybe set org.eclipse.aether.ConfigurationProperties.USER_AGENT with netbeans specific value. - Map toRet = new HashMap(); + Map toRet = new HashMap<>(); String options = getPreferences().get(PROP_DEFAULT_OPTIONS, ""); try { diff --git a/java/maven.embedder/src/org/netbeans/modules/maven/embedder/MavenEmbedder.java b/java/maven.embedder/src/org/netbeans/modules/maven/embedder/MavenEmbedder.java index 7f36705d0693..9cbd3924315c 100644 --- a/java/maven.embedder/src/org/netbeans/modules/maven/embedder/MavenEmbedder.java +++ b/java/maven.embedder/src/org/netbeans/modules/maven/embedder/MavenEmbedder.java @@ -142,8 +142,8 @@ public final class MavenEmbedder { settingsDecrypter = plexus.lookup(SettingsDecrypter.class); VersionResolver vr = plexus.lookup(VersionResolver.class); - if (vr instanceof NbVersionResolver2) { - versionResolver = (NbVersionResolver2)vr; + if (vr instanceof NbVersionResolver2 vr2) { + versionResolver = vr2; } else { versionResolver = null; } @@ -454,7 +454,7 @@ public MavenExecutionResult execute(MavenExecutionRequest req) { */ public List createModelLineage(File pom) throws ModelBuildingException { ModelBuildingResult res = executeModelBuilder(pom); - List toRet = new ArrayList(); + List toRet = new ArrayList<>(); for (String id : res.getModelIds()) { Model m = res.getRawModel(id); @@ -550,12 +550,12 @@ public List getLifecyclePhases() { LifecycleMapping lifecycleMapping = lookupComponent(LifecycleMapping.class); if (lifecycleMapping != null) { - Set phases = new TreeSet(); + Set phases = new TreeSet<>(); Map lifecycles = lifecycleMapping.getLifecycles(); for (Lifecycle lifecycle : lifecycles.values()) { phases.addAll(lifecycle.getPhases().keySet()); } - return new ArrayList(phases); + return new ArrayList<>(phases); } return Collections.emptyList(); diff --git a/java/maven.embedder/src/org/netbeans/modules/maven/embedder/NBRepositoryModelResolver.java b/java/maven.embedder/src/org/netbeans/modules/maven/embedder/NBRepositoryModelResolver.java index df9839131eca..84681bf36364 100644 --- a/java/maven.embedder/src/org/netbeans/modules/maven/embedder/NBRepositoryModelResolver.java +++ b/java/maven.embedder/src/org/netbeans/modules/maven/embedder/NBRepositoryModelResolver.java @@ -34,7 +34,6 @@ import org.apache.maven.model.resolution.ModelResolver; import org.apache.maven.model.resolution.UnresolvableModelException; import org.apache.maven.repository.RepositorySystem; -import org.openide.util.Exceptions; /** * @@ -44,7 +43,7 @@ class NBRepositoryModelResolver implements ModelResolver { private final MavenEmbedder embedder; - private List remoteRepositories = new ArrayList(); + private List remoteRepositories = new ArrayList<>(); NBRepositoryModelResolver(MavenEmbedder embedder) { @@ -53,7 +52,7 @@ class NBRepositoryModelResolver private NBRepositoryModelResolver(NBRepositoryModelResolver original) { this(original.embedder); - this.remoteRepositories = new ArrayList(original.remoteRepositories); + this.remoteRepositories = new ArrayList<>(original.remoteRepositories); } @Override @@ -72,10 +71,8 @@ public ModelSource resolveModel(String groupId, String artifactId, String versio Artifact artifactParent = embedder.lookupComponent(RepositorySystem.class).createProjectArtifact(groupId, artifactId, version); try { embedder.resolveArtifact(artifactParent, remoteRepositories, embedder.getLocalRepository()); - } catch (ArtifactResolutionException ex) { + } catch (ArtifactResolutionException | ArtifactNotFoundException ex) { throw new UnresolvableModelException(ex.getMessage(), groupId , artifactId , version ); - } catch (ArtifactNotFoundException ex) { - throw new UnresolvableModelException( ex.getMessage(), groupId , artifactId , version ); } return new FileModelSource(artifactParent.getFile());