Skip to content

Commit

Permalink
Avoid overhead of listener broadcasting for project observation listener
Browse files Browse the repository at this point in the history
The broadcaster infrastructure adds a non signigicant overhead. This listener gets called for each project dependency
for every resolution, and seemingly causes a performance hit.
  • Loading branch information
jvandort committed May 8, 2024
1 parent fc38d11 commit 11fb170
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import org.gradle.internal.build.BuildState
import org.gradle.internal.service.scopes.Scope
import org.gradle.internal.service.scopes.ServiceScope
import org.gradle.util.Path
import java.util.concurrent.ConcurrentHashMap


@ServiceScope(Scope.Build::class)
Expand All @@ -33,7 +34,7 @@ class RelevantProjectsRegistry(
) : ProjectComponentObservationListener {

private
val targetProjects = mutableSetOf<ProjectState>()
val targetProjects = ConcurrentHashMap.newKeySet<ProjectState>()

fun relevantProjects(nodes: List<Node>): Set<ProjectState> {
val result = mutableSetOf<ProjectState>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package org.gradle.configurationcache.fingerprint

import org.gradle.api.internal.artifacts.configurations.ProjectComponentObservationListener
import org.gradle.api.internal.file.FileCollectionFactory
import org.gradle.api.internal.file.FileCollectionInternal
import org.gradle.api.internal.file.collections.DirectoryFileTreeFactory
Expand Down Expand Up @@ -64,6 +65,7 @@ import org.gradle.util.internal.GFileUtils
import java.io.File
import java.net.URI
import java.nio.file.Files
import java.util.concurrent.ConcurrentHashMap
import java.util.function.Supplier


Expand Down Expand Up @@ -92,7 +94,7 @@ class ConfigurationCacheFingerprintController internal constructor(
private val agentStatus: AgentStatus,
private val problems: ConfigurationCacheProblems,
private val encryptionService: EncryptionService
) : Stoppable, ProjectScopedScriptResolution {
) : Stoppable, ProjectScopedScriptResolution, ProjectComponentObservationListener {

interface Host {
val valueSourceProviderFactory: ValueSourceProviderFactory
Expand All @@ -102,6 +104,9 @@ class ConfigurationCacheFingerprintController internal constructor(
private
val fileCollectionFingerprinter = fingerprinterRegistry.getFingerprinter(DefaultFileNormalizationSpec.from(InputNormalizer.ABSOLUTE_PATH, DirectorySensitivity.DEFAULT, LineEndingSensitivity.DEFAULT))

private
val projectObservationListeners = ConcurrentHashMap.newKeySet<ProjectComponentObservationListener>()

private
abstract class WritingState {

Expand Down Expand Up @@ -297,13 +302,19 @@ class ConfigurationCacheFingerprintController internal constructor(
listenerManager.addListener(listener)
workInputListeners.addListener(listener)
scriptFileResolverListeners.addListener(listener)
projectObservationListeners.add(listener)
}

private
fun removeListener(listener: ConfigurationCacheFingerprintWriter) {
scriptFileResolverListeners.removeListener(listener)
workInputListeners.removeListener(listener)
listenerManager.removeListener(listener)
projectObservationListeners.remove(listener)
}

override fun projectObserved(consumingProjectPath: Path?, targetProjectPath: Path) {
projectObservationListeners.forEach { it.projectObserved(consumingProjectPath, targetProjectPath) }
}

private
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,13 @@

package org.gradle.api.internal.artifacts.configurations;

import org.gradle.internal.service.scopes.EventScope;
import org.gradle.internal.service.scopes.Scope;
import org.gradle.internal.service.scopes.StatefulListener;
import org.gradle.util.Path;

import javax.annotation.Nullable;

/**
* A listener that is notified when one project observes the local component metadata of another.
*/
@StatefulListener
@EventScope(Scope.Build.class)
public interface ProjectComponentObservationListener {
/**
* Called when one project observes the local component metadata of another project.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@
import org.gradle.api.internal.artifacts.ProjectComponentIdentifierInternal;
import org.gradle.api.internal.artifacts.configurations.ProjectComponentObservationListener;
import org.gradle.internal.component.local.model.LocalComponentGraphResolveState;
import org.gradle.internal.event.ListenerManager;
import org.gradle.util.Path;

import javax.annotation.Nullable;
import javax.inject.Inject;
import java.util.List;

/**
* A simple dependency-management scoped wrapper around {@link BuildTreeLocalComponentProvider} that
Expand All @@ -36,18 +36,18 @@
public class DefaultLocalComponentRegistry implements LocalComponentRegistry {
private final Path currentProjectPath;
private final Path currentBuildPath;
private final ProjectComponentObservationListener projectComponentObservationListener;
private final List<ProjectComponentObservationListener> projectComponentObservationListeners;
private final BuildTreeLocalComponentProvider componentProvider;

@Inject
public DefaultLocalComponentRegistry(
DomainObjectContext domainObjectContext,
ListenerManager listenerManager,
List<ProjectComponentObservationListener> projectComponentObservationListeners,
BuildTreeLocalComponentProvider componentProvider
) {
this.currentProjectPath = getProjectIdentityPath(domainObjectContext);
this.currentBuildPath = domainObjectContext.getBuildPath();
this.projectComponentObservationListener = listenerManager.getBroadcaster(ProjectComponentObservationListener.class);
this.projectComponentObservationListeners = projectComponentObservationListeners;
this.componentProvider = componentProvider;
}

Expand All @@ -62,7 +62,9 @@ public LocalComponentGraphResolveState getComponent(ProjectComponentIdentifier p
// Specifically, the following test breaks when we remove this check:
// IsolatedProjectsToolingApiIdeaProjectIntegrationTest.ensures unique name for all Idea modules in composite
if (projectIdentifier.getBuild().getBuildPath().equals(currentBuildPath.getPath())) {
projectComponentObservationListener.projectObserved(currentProjectPath, targetProjectPath);
for (ProjectComponentObservationListener listener : projectComponentObservationListeners) {
listener.projectObserved(currentProjectPath, targetProjectPath);
}
}

}
Expand Down

0 comments on commit 11fb170

Please sign in to comment.