summaryrefslogtreecommitdiffstats
path: root/src/build_log.cc
diff options
context:
space:
mode:
authorNico Weber <nicolasweber@gmx.de>2012-05-10 05:20:52 (GMT)
committerNico Weber <nicolasweber@gmx.de>2012-05-10 05:39:03 (GMT)
commite5b244dd656eaa7b99fcbd5abddc94a82d14950c (patch)
tree02bb8bdbdede3baa00b24f5d676fe9268b958e1e /src/build_log.cc
parent040ff5435ee8091ad20294be54a6de532f515263 (diff)
downloadNinja-e5b244dd656eaa7b99fcbd5abddc94a82d14950c.zip
Ninja-e5b244dd656eaa7b99fcbd5abddc94a82d14950c.tar.gz
Ninja-e5b244dd656eaa7b99fcbd5abddc94a82d14950c.tar.bz2
Switch LineReader from fgets() to just fread().
fgets() needs to search for a \n in the input, and LineReader's strstr() did the same work again. By using fread() directly, this duplicate work can be saved. (I tried using readline() / fgetln() for the same saving, but those functions are not standard, and were slower than the code in this CL.) Results from running build_log_perftest, on OS X: Before: min 369ms max 372ms avg 370.4ms After: min 243ms max 247ms avg 244.8ms On Windows: Before: min 796ms max 904ms avg 858.0ms After: min 359ms max 375ms avg 371.4ms On Linux: Before: min 161ms max 169ms avg 164.8ms Before: min 130ms max 137ms avg 132.6ms
Diffstat (limited to 'src/build_log.cc')
-rw-r--r--src/build_log.cc38
1 files changed, 33 insertions, 5 deletions
diff --git a/src/build_log.cc b/src/build_log.cc
index 01fb001..5803ada 100644
--- a/src/build_log.cc
+++ b/src/build_log.cc
@@ -113,24 +113,52 @@ void BuildLog::Close() {
class LineReader {
public:
- explicit LineReader(FILE* file) : file_(file) {}
+ explicit LineReader(FILE* file)
+ : file_(file), buf_end_(buf_), line_start_(buf_), line_end_(NULL) {}
// Reads a \n-terminated line from the file passed to the constructor.
// On return, *line_start points to the beginning of the next line, and
// *line_end points to the \n at the end of the line. If no newline is seen
// in a fixed buffer size, *line_end is set to NULL. Returns false on EOF.
bool ReadLine(char** line_start, char** line_end) {
- if (!fgets(buf_, sizeof(buf_), file_))
- return false;
+ if (line_start_ >= buf_end_ || !line_end_) {
+ // Buffer empty, refill.
+ size_t size_read = fread(buf_, 1, sizeof(buf_), file_);
+ if (!size_read)
+ return false;
+ line_start_ = buf_;
+ buf_end_ = buf_ + size_read;
+ } else {
+ // Advance to next line in buffer.
+ line_start_ = line_end_ + 1;
+ }
- *line_start = buf_;
- *line_end = strchr(buf_, '\n');
+ line_end_ = (char*)memchr(line_start_, '\n', buf_end_ - line_start_);
+ if (!line_end_) {
+ // No newline. Move rest of data to start of buffer, fill rest.
+ size_t already_consumed = line_start_ - buf_;
+ size_t size_rest = (buf_end_ - buf_) - already_consumed;
+ memmove(buf_, line_start_, size_rest);
+
+ size_t read = fread(buf_ + size_rest, 1, sizeof(buf_) - size_rest, file_);
+ buf_end_ = buf_ + size_rest + read;
+ line_start_ = buf_;
+ line_end_ = (char*)memchr(line_start_, '\n', buf_end_ - line_start_);
+ }
+
+ *line_start = line_start_;
+ *line_end = line_end_;
return true;
}
private:
FILE* file_;
char buf_[256 << 10];
+ char* buf_end_; // Points one past the last valid byte in |buf_|.
+
+ char* line_start_;
+ // Points at the next \n in buf_ after line_start, or NULL.
+ char* line_end_;
};
bool BuildLog::Load(const string& path, string* err) {