aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2017-02-23 20:40:15 +0000
committerGravatar Irina Iancu <elenairina@google.com>2017-02-24 08:30:01 +0000
commit5582d89edc452fd51ff95879e3904a67ec0e398e (patch)
treeea795d94e2d8adfaa14b007a7d7e4b49c70a8c2f /src/main/java/com/google
parent67fa75a4bd5bb1f602d7f4575e2cf2bed77bbb97 (diff)
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
Diffstat (limited to 'src/main/java/com/google')
-rw-r--r--src/main/java/com/google/devtools/build/lib/util/PersistentMap.java42
1 files changed, 32 insertions, 10 deletions
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<K, V> extends ForwardingMap<K, V> {
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<K, V> extends ForwardingMap<K, V> {
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<K, V> extends ForwardingMap<K, V> {
} finally {
in.close();
}
+
+ LOG.info(String.format("Loaded cache '%s' [%s bytes]", mapFile, fileSize));
}
/**