From 5582d89edc452fd51ff95879e3904a67ec0e398e Mon Sep 17 00:00:00 2001 From: Googler Date: Thu, 23 Feb 2017 20:40:15 +0000 Subject: Read the PersistentMap's backing file into memory all at once when processing it. We are going to read the whole thing and convert it into data structures, anyway. This shaves some time off of server startup time. -- PiperOrigin-RevId: 148377493 MOS_MIGRATED_REVID=148377493 --- .../devtools/build/lib/util/PersistentMap.java | 42 ++++++++++++++++------ 1 file changed, 32 insertions(+), 10 deletions(-) (limited to 'src/main/java/com') diff --git a/src/main/java/com/google/devtools/build/lib/util/PersistentMap.java b/src/main/java/com/google/devtools/build/lib/util/PersistentMap.java index 56ac9a1b2b..4a7348645f 100644 --- a/src/main/java/com/google/devtools/build/lib/util/PersistentMap.java +++ b/src/main/java/com/google/devtools/build/lib/util/PersistentMap.java @@ -15,18 +15,22 @@ package com.google.devtools.build.lib.util; import com.google.common.collect.ForwardingMap; +import com.google.common.io.ByteStreams; import com.google.devtools.build.lib.vfs.FileSystemUtils; import com.google.devtools.build.lib.vfs.Path; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; +import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.io.InputStream; import java.util.HashMap; import java.util.Hashtable; import java.util.LinkedHashMap; import java.util.Map; +import java.util.logging.Logger; /** * A map that is backed by persistent storage. It uses two files on disk for @@ -65,8 +69,10 @@ import java.util.Map; public abstract class PersistentMap extends ForwardingMap { private static final int MAGIC = 0x20071105; - private static final int ENTRY_MAGIC = 0xfe; + private static final int MIN_MAPFILE_SIZE = 16; + private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; + private static final Logger LOG = Logger.getLogger(PersistentMap.class.getName()); private final int version; private final Path mapFile; @@ -334,16 +340,30 @@ public abstract class PersistentMap extends ForwardingMap { if (!mapFile.exists()) { return; } - DataInputStream in = new DataInputStream(new BufferedInputStream(mapFile.getInputStream())); - try { - long fileSize = mapFile.getFileSize(); - if (fileSize < (16)) { - if (failFast) { - throw new IOException(mapFile + " is too short: Only " + fileSize + " bytes"); - } else { - return; - } + + long fileSize = mapFile.getFileSize(); + if (fileSize < MIN_MAPFILE_SIZE) { + if (failFast) { + throw new IOException(mapFile + " is too short: Only " + fileSize + " bytes"); + } else { + return; } + } else if (fileSize > MAX_ARRAY_SIZE) { + if (failFast) { + throw new IOException(mapFile + " is too long: " + fileSize + " bytes"); + } else { + return; + } + } + + // We read the whole file up front as a performance optimization; otherwise calling available() + // on the stream over and over does a lot of syscalls. + byte[] mapBytes; + try (InputStream fileInput = mapFile.getInputStream()) { + mapBytes = ByteStreams.toByteArray(new BufferedInputStream(fileInput)); + } + DataInputStream in = new DataInputStream(new ByteArrayInputStream(mapBytes)); + try { if (in.readLong() != MAGIC) { // not a PersistentMap if (failFast) { throw new IOException("Unexpected format"); @@ -360,6 +380,8 @@ public abstract class PersistentMap extends ForwardingMap { } finally { in.close(); } + + LOG.info(String.format("Loaded cache '%s' [%s bytes]", mapFile, fileSize)); } /** -- cgit v1.2.3