diff options
author | Dan Willemsen <dwillemsen@google.com> | 2016-10-19 16:16:21 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@google.com> | 2016-11-07 13:57:33 -0800 |
commit | c9b5eaa55231612aeff85385033a792949162228 (patch) | |
tree | e3c75588da8febd55d106daffae8ab00f7babbda | |
parent | 04f4bc5dbbc9bfb96ef75f577e919082c8690ae9 (diff) | |
download | ninja-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.cc | 12 |
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)) { |