From 825946bb036c10b0340d02638b18cec2edb2a5c2 Mon Sep 17 00:00:00 2001 From: janakr Date: Sun, 8 Apr 2018 20:28:09 -0700 Subject: Serialize Artifacts by their root-relative path rather than their exec path. The exec path contains redundant information when considered with the ArtifactRoot, so, since the ArtifactRoot is memoized, we can save space and time by only serializing the non-redundant root-relative path part. PiperOrigin-RevId: 192076469 --- .../devtools/build/lib/actions/Artifact.java | 50 ++++++++++++++++++---- 1 file changed, 41 insertions(+), 9 deletions(-) (limited to 'src/main') diff --git a/src/main/java/com/google/devtools/build/lib/actions/Artifact.java b/src/main/java/com/google/devtools/build/lib/actions/Artifact.java index 58c72204a3..68af8179d5 100644 --- a/src/main/java/com/google/devtools/build/lib/actions/Artifact.java +++ b/src/main/java/com/google/devtools/build/lib/actions/Artifact.java @@ -166,6 +166,32 @@ public class Artifact private final PathFragment rootRelativePath; private final ArtifactOwner owner; + /** + * The {@code rootRelativePath is a few characters shorter than the {@code execPath} for derived + * artifacts, so we save a few bytes by serializing it rather than the {@code execPath}, + * especially when the {@code root} is common to many artifacts and therefore memoized. + */ + @AutoCodec.VisibleForSerialization + @AutoCodec.Instantiator + static Artifact createForSerialization( + ArtifactRoot root, ArtifactOwner owner, PathFragment rootRelativePath) { + if (rootRelativePath == null || rootRelativePath.isAbsolute() != root.getRoot().isAbsolute()) { + throw new IllegalArgumentException( + rootRelativePath + + ": illegal rootRelativePath for " + + rootRelativePath + + " (root: " + + root + + ")"); + } + PathFragment rootExecPath = root.getExecPath(); + return new Artifact( + root, + rootExecPath.isEmpty() ? rootRelativePath : rootExecPath.getRelative(rootRelativePath), + rootRelativePath, + owner); + } + /** * Constructs an artifact for the specified path, root and execPath. The root must be an ancestor * of path, and execPath must be a non-absolute tail of path. Outside of testing, this method @@ -186,13 +212,24 @@ public class Artifact * */ @VisibleForTesting - @AutoCodec.Instantiator public Artifact(ArtifactRoot root, PathFragment execPath, ArtifactOwner owner) { - Preconditions.checkNotNull(root); - if (execPath == null || execPath.isAbsolute() != root.getRoot().isAbsolute()) { + this( + Preconditions.checkNotNull(root), + Preconditions.checkNotNull(execPath, "Null execPath not allowed (root %s", root), + root.getExecPath().isEmpty() ? execPath : execPath.relativeTo(root.getExecPath()), + Preconditions.checkNotNull(owner)); + if (execPath.isAbsolute() != root.getRoot().isAbsolute()) { throw new IllegalArgumentException( execPath + ": illegal execPath for " + execPath + " (root: " + root + ")"); } + } + + private Artifact( + ArtifactRoot root, + PathFragment execPath, + PathFragment rootRelativePath, + ArtifactOwner owner) { + Preconditions.checkNotNull(root); if (execPath.isEmpty()) { throw new IllegalArgumentException( "it is illegal to create an artifact with an empty execPath"); @@ -200,12 +237,7 @@ public class Artifact this.hashCode = execPath.hashCode(); this.root = root; this.execPath = execPath; - PathFragment rootExecPath = root.getExecPath(); - if (rootExecPath.isEmpty()) { - this.rootRelativePath = execPath; - } else { - this.rootRelativePath = execPath.relativeTo(root.getExecPath()); - } + this.rootRelativePath = rootRelativePath; this.owner = Preconditions.checkNotNull(owner); } -- cgit v1.2.3