SourceArtifacts are interned on deserialization using an ArtifactFactory. This should reduce memory consumption in NestedSet deserialization, which currently does not recycle Artifact instances.
PiperOrigin-RevId: 194083901
diff --git a/src/test/java/com/google/devtools/build/lib/actions/ArtifactTest.java b/src/test/java/com/google/devtools/build/lib/actions/ArtifactTest.java
index ccec350..abbd347 100644
--- a/src/test/java/com/google/devtools/build/lib/actions/ArtifactTest.java
+++ b/src/test/java/com/google/devtools/build/lib/actions/ArtifactTest.java
@@ -17,14 +17,19 @@
import static org.junit.Assert.fail;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.devtools.build.lib.actions.ActionAnalysisMetadata.MiddlemanType;
+import com.google.devtools.build.lib.actions.Artifact.SourceArtifact;
+import com.google.devtools.build.lib.actions.ArtifactResolver.ArtifactResolverSupplier;
import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
import com.google.devtools.build.lib.actions.util.LabelArtifactOwner;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.rules.cpp.CppFileTypes;
import com.google.devtools.build.lib.rules.java.JavaSemantics;
+import com.google.devtools.build.lib.skyframe.serialization.AutoRegistry;
+import com.google.devtools.build.lib.skyframe.serialization.ObjectCodecs;
import com.google.devtools.build.lib.skyframe.serialization.testutils.SerializationTester;
import com.google.devtools.build.lib.testutil.MoreAsserts;
import com.google.devtools.build.lib.testutil.Scratch;
@@ -320,6 +325,43 @@
}
@Test
+ public void testCodecRecyclesSourceArtifactInstances() throws Exception {
+ Root root = Root.fromPath(scratch.dir("/"));
+ ArtifactRoot artifactRoot = ArtifactRoot.asSourceRoot(root);
+ ArtifactFactory artifactFactory = new ArtifactFactory(execDir, "blaze-out");
+ artifactFactory.setSourceArtifactRoots(ImmutableMap.of(root, artifactRoot));
+ ArtifactResolverSupplier artifactResolverSupplierForTest = () -> artifactFactory;
+
+ OutputBaseSupplier outputBaseSupplier = () -> scratch.getFileSystem().getPath("/");
+ ObjectCodecs objectCodecs =
+ new ObjectCodecs(
+ AutoRegistry.get()
+ .getBuilder()
+ .addReferenceConstant(scratch.getFileSystem())
+ .setAllowDefaultCodec(true)
+ .build(),
+ ImmutableMap.of(
+ FileSystem.class, scratch.getFileSystem(),
+ OutputBaseSupplier.class, outputBaseSupplier,
+ ArtifactResolverSupplier.class, artifactResolverSupplierForTest));
+
+ PathFragment pathFragment = PathFragment.create("src/foo.cc");
+ ArtifactOwner owner = new LabelArtifactOwner(Label.parseAbsoluteUnchecked("//foo:bar"));
+ SourceArtifact sourceArtifact = new SourceArtifact(artifactRoot, pathFragment, owner);
+ SourceArtifact deserialized1 =
+ (SourceArtifact) objectCodecs.deserialize(objectCodecs.serialize(sourceArtifact));
+ SourceArtifact deserialized2 =
+ (SourceArtifact) objectCodecs.deserialize(objectCodecs.serialize(sourceArtifact));
+ assertThat(deserialized1).isSameAs(deserialized2);
+
+ Artifact sourceArtifactFromFactory =
+ artifactFactory.getSourceArtifact(pathFragment, root, owner);
+ Artifact deserialized =
+ (Artifact) objectCodecs.deserialize(objectCodecs.serialize(sourceArtifactFromFactory));
+ assertThat(sourceArtifactFromFactory).isSameAs(deserialized);
+ }
+
+ @Test
public void testLongDirname() throws Exception {
String dirName = createDirNameArtifact().getDirname();