summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Willemsen <dwillemsen@google.com>2016-10-19 16:16:21 -0700
committerDan Willemsen <dwillemsen@google.com>2016-11-07 13:57:33 -0800
commitc9b5eaa55231612aeff85385033a792949162228 (patch)
treee3c75588da8febd55d106daffae8ab00f7babbda
parent04f4bc5dbbc9bfb96ef75f577e919082c8690ae9 (diff)
downloadninja-c9b5eaa55231612aeff85385033a792949162228.tar.gz
Optimize ReadFile allocations
Instead of continuously reallocating the output string, call reserve() up front to enlarge the string's buffer. Also use feof() instead of an empty read to detect the end of the file. This saves a syscall on <64kb files, which is about 5% (200ns) of the time to read a file on my machine. For our larger build.ninja files (~550MB), this saves about 500ms, which is more than half the time spent in this function. (Measured by adding METRICS_RECORD to this function during manifest_parser_perftest) For the standard manifest_parser_perftest, this only saves ~20ms out of ~600ms for a full run.
-rw-r--r--src/util.cc12
1 files changed, 11 insertions, 1 deletions
diff --git a/src/util.cc b/src/util.cc
index e31fd1f..de280cd 100644
--- a/src/util.cc
+++ b/src/util.cc
@@ -380,9 +380,19 @@ int ReadFile(const string& path, string* contents, string* err) {
return -errno;
}
+ struct stat st;
+ if (fstat(fileno(f), &st) < 0) {
+ err->assign(strerror(errno));
+ fclose(f);
+ return -errno;
+ }
+
+ // +1 is for the resize in ManifestParser::Load
+ contents->reserve(st.st_size + 1);
+
char buf[64 << 10];
size_t len;
- while ((len = fread(buf, 1, sizeof(buf), f)) > 0) {
+ while (!feof(f) && (len = fread(buf, 1, sizeof(buf), f)) > 0) {
contents->append(buf, len);
}
if (ferror(f)) {