Skip to content

Commit

Permalink
perf: Improve performance of Quarkus deployment jar support
Browse files Browse the repository at this point in the history
Fixes #1143

Signed-off-by: azerr <[email protected]>
  • Loading branch information
angelozerr committed Oct 10, 2023
1 parent 7d107b0 commit f2da00a
Show file tree
Hide file tree
Showing 9 changed files with 379 additions and 149 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,10 @@ public interface Listener {

private final Project project;

private final List<RunnableProgress> preprocessors;

public ClasspathResourceChangedManager(Project project) {
this.project = project;
this.preprocessors = new ArrayList<>();
// Send source files changed in debounce mode
this.resourceChangedNotifier = new ClasspathResourceChangedNotifier(project, preprocessors);
this.resourceChangedNotifier = new ClasspathResourceChangedNotifier(project);
listener = new ClasspathResourceChangedListener(this);
projectConnection = project.getMessageBus().connect();
// Track end of Java libraries update
Expand Down Expand Up @@ -105,13 +102,4 @@ Project getProject() {
ClasspathResourceChangedNotifier getResourceChangedNotifier() {
return resourceChangedNotifier;
}

/**
* Add a preprocessor to update classpatch when a library changed before sending the {@link Listener#librariesChanged()} event.
*
* @param preprocessor the preprocessor to add.
*/
public void addPreprocessor(RunnableProgress preprocessor) {
preprocessors.add(preprocessor);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@
package com.redhat.devtools.intellij.lsp4mp4ij.classpath;

import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.progress.EmptyProgressIndicator;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
Expand All @@ -27,10 +25,10 @@
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.HashSet;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;

/**
* Source file change notifier with a debounce mode.
Expand All @@ -46,12 +44,10 @@ public class ClasspathResourceChangedNotifier implements Disposable {

private final Set<Pair<VirtualFile, Module>> sourceFiles;
private boolean librariesChanged;
private final List<RunnableProgress> processBeforeLibrariesChanged;
private boolean disposed;

public ClasspathResourceChangedNotifier(Project project, List<RunnableProgress> preprocessors) {
public ClasspathResourceChangedNotifier(Project project) {
this.project = project;
this.processBeforeLibrariesChanged = preprocessors;
sourceFiles = new HashSet<>();
}

Expand Down Expand Up @@ -107,11 +103,7 @@ private void notifyChanges() {
}
if (librariesChanged) {
// Java Libraries has changed
if (processBeforeLibrariesChanged.isEmpty() || ApplicationManager.getApplication().isUnitTestMode()) {
// No preprocessor or Test context, send directly the librariesChanged event.
for (var runnable : processBeforeLibrariesChanged) {
runnable.run(new EmptyProgressIndicator());
}
if (ApplicationManager.getApplication().isUnitTestMode()) {
// Send the libraries changed event
project.getMessageBus().syncPublisher(ClasspathResourceChangedManager.TOPIC).librariesChanged();
librariesChanged = false;
Expand All @@ -125,9 +117,6 @@ public void run(@NotNull ProgressIndicator progressIndicator) {
// Execute preprocessor
progressIndicator.setIndeterminate(false);
progressIndicator.checkCanceled();
for (var runnable : processBeforeLibrariesChanged) {
runnable.run(progressIndicator);
}
} finally {
// Send the libraries changed event
project.getMessageBus().syncPublisher(ClasspathResourceChangedManager.TOPIC).librariesChanged();
Expand All @@ -152,7 +141,7 @@ public void dispose() {
this.disposed = true;
if (debounceTask != null) {
debounceTask.cancel();
debounceTask =null;
debounceTask = null;
}
if (debounceTimer != null) {
debounceTimer.cancel();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public static boolean isQuarkusExtensionWithDeploymentArtifact(Library library)
if (library != null) {
VirtualFile[] files = library.getFiles(OrderRootType.CLASSES);

for(int i=0; !result && i < files.length;++i) {
for (int i = 0; !result && i < files.length; ++i) {
if (files[i].isDirectory()) {
result = ToolDelegate.getDeploymentJarId(VfsUtilCore.virtualToIoFile(files[i])) != null;
}
Expand All @@ -77,7 +77,7 @@ public static boolean isQuarkusExtensionWithDeploymentArtifact(Library library)
/**
* Check if the Quarkus library needs to be recomputed and update it if required.
*
* @param module the module to check
* @param module the module to check
* @param progressIndicator
*/
public static void ensureQuarkusLibrary(Module module, ProgressIndicator progressIndicator) {
Expand All @@ -95,20 +95,28 @@ public static void ensureQuarkusLibrary(Module module, ProgressIndicator progres
Integer actualHash = computeHash(module);
var qlib = OrderEntryUtil.findLibraryOrderEntry(ModuleRootManager.getInstance(module), QuarkusConstants.QUARKUS_DEPLOYMENT_LIBRARY_NAME);
if (qlib == null || (actualHash != null && !actualHash.equals(previousHash)) ||
!QuarkusConstants.QUARKUS_DEPLOYMENT_LIBRARY_VERSION.equals(component.getVersion())){
!QuarkusConstants.QUARKUS_DEPLOYMENT_LIBRARY_VERSION.equals(component.getVersion())) {
ModuleRootModificationUtil.updateModel(module, model -> {
LibraryTable table = model.getModuleLibraryTable();
Library library = table.getLibraryByName(QuarkusConstants.QUARKUS_DEPLOYMENT_LIBRARY_NAME);
while (library != null) {
table.removeLibrary(library);
TelemetryService.instance().action(TelemetryService.MODEL_PREFIX + "removeLibrary");
try {
TelemetryService.instance().action(TelemetryService.MODEL_PREFIX + "removeLibrary");
} catch (Exception e) {

}
library = table.getLibraryByName(QuarkusConstants.QUARKUS_DEPLOYMENT_LIBRARY_NAME);
}
progressIndicator.checkCanceled();
progressIndicator.setText("Collecting Quarkus deployment dependencies...");
List<VirtualFile>[] files = toolDelegate.getDeploymentFiles(module, progressIndicator);
LOGGER.info("Adding library to " + module.getName() + " previousHash=" + previousHash + " newHash=" + actualHash);
TelemetryService.instance().action(TelemetryService.MODEL_PREFIX + "addLibrary").send();
try {
TelemetryService.instance().action(TelemetryService.MODEL_PREFIX + "addLibrary").send();
} catch (Exception e) {

}
addLibrary(model, files, module);
});
component.setHash(actualHash);
Expand All @@ -120,7 +128,7 @@ public static void ensureQuarkusLibrary(Module module, ProgressIndicator progres
}

private static void addLibrary(ModifiableRootModel model, List<VirtualFile>[] files, Module module) {
LibraryEx library = (LibraryEx)model.getModuleLibraryTable().createLibrary(QuarkusConstants.QUARKUS_DEPLOYMENT_LIBRARY_NAME);
LibraryEx library = (LibraryEx) model.getModuleLibraryTable().createLibrary(QuarkusConstants.QUARKUS_DEPLOYMENT_LIBRARY_NAME);
LibraryEx.ModifiableModelEx libraryModel = library.getModifiableModel();

for (VirtualFile rootFile : files[ToolDelegate.BINARY]) {
Expand All @@ -145,14 +153,14 @@ private static Integer computeHash(Module module) {
@Override
public Set<String> visitLibraryOrderEntry(@NotNull LibraryOrderEntry libraryOrderEntry, Set<String> value) {
if (!isQuarkusDeploymentLibrary(libraryOrderEntry) && isQuarkusExtensionWithDeploymentArtifact(libraryOrderEntry.getLibrary())) {
for(VirtualFile file : libraryOrderEntry.getFiles(OrderRootType.CLASSES)) {
for (VirtualFile file : libraryOrderEntry.getFiles(OrderRootType.CLASSES)) {
value.add(file.getPath());
}
}
return value;
}
}, new HashSet<>());
return files.isEmpty()?null:files.hashCode();
return files.isEmpty() ? null : files.hashCode();
}

/**
Expand All @@ -174,7 +182,7 @@ public Boolean visitLibraryOrderEntry(@NotNull LibraryOrderEntry libraryOrderEnt
}

public static boolean isQuarkusLibrary(@NotNull LibraryOrderEntry libraryOrderEntry) {
return libraryOrderEntry.getLibraryName() != null &&
return libraryOrderEntry.getLibraryName() != null &&
libraryOrderEntry.getLibraryName().contains(QuarkusConstants.QUARKUS_CORE_PREFIX);
}

Expand Down Expand Up @@ -204,9 +212,9 @@ public static boolean checkQuarkusVersion(Module module, Predicate<Matcher> pred
.findFirst();
if (quarkusCoreJar.isPresent()) {
Matcher quarkusCoreArtifactMatcher = QUARKUS_CORE_PATTERN.matcher(quarkusCoreJar.get().getName());
if(quarkusCoreArtifactMatcher.matches()) {
if (quarkusCoreArtifactMatcher.matches()) {
String quarkusVersion = quarkusCoreArtifactMatcher.group(1);
LOGGER.debug("Detected Quarkus version = " + quarkusVersion);
LOGGER.debug("Detected Quarkus version = " + quarkusVersion);
Matcher quarkusVersionMatcher = QUARKUS_STANDARD_VERSIONING.matcher(quarkusVersion);
return predicate.test(quarkusVersionMatcher);
} else {
Expand All @@ -219,7 +227,7 @@ public static boolean checkQuarkusVersion(Module module, Predicate<Matcher> pred

public static Set<String> getModulesURIs(Project project) {
Set<String> uris = new HashSet<>();
for(Module module : ModuleManager.getInstance(project).getModules()) {
for (Module module : ModuleManager.getInstance(project).getModules()) {
uris.add(PsiUtilsLSImpl.getProjectURI(module));
}
return uris;
Expand Down
Loading

0 comments on commit f2da00a

Please sign in to comment.