From 107b61bbccc5b6554084877853699e2f5ea86db3 Mon Sep 17 00:00:00 2001 From: Vladimir Marko Date: Tue, 23 Jun 2015 15:39:01 +0100 Subject: [PATCH] ART: Improve Indenter performance. This reduces the time taken by oatdump_test by ~15s (16%) on host and ~30s (5%) on N5. The Indenter.overflow() was previously the hottest function according to perf. Change-Id: I96eb69ce3f5420cd09dba23b29f8025cedc3d80a --- runtime/indenter.h | 71 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 20 deletions(-) diff --git a/runtime/indenter.h b/runtime/indenter.h index d055d4e3f..38b398de4 100644 --- a/runtime/indenter.h +++ b/runtime/indenter.h @@ -27,45 +27,76 @@ const size_t kIndentBy1Count = 2; class Indenter : public std::streambuf { public: Indenter(std::streambuf* out, char text, size_t count) - : indent_next_(true), out_sbuf_(out), text_(text), count_(count) {} + : indent_next_(true), out_sbuf_(out), + text_{text, text, text, text, text, text, text, text}, // NOLINT(whitespace/braces) + count_(count) {} private: - int_type overflow(int_type c) { + std::streamsize xsputn(const char* s, std::streamsize n) OVERRIDE { + std::streamsize result = n; // Aborts on failure. + const char* eol = static_cast(memchr(s, '\n', n)); + while (eol != nullptr) { + size_t to_write = eol + 1 - s; + Write(s, to_write); + s += to_write; + n -= to_write; + indent_next_ = true; + eol = static_cast(memchr(s, '\n', n)); + } + if (n != 0u) { + Write(s, n); + } + return result; + } + + int_type overflow(int_type c) OVERRIDE { if (UNLIKELY(c == std::char_traits::eof())) { out_sbuf_->pubsync(); return c; } - if (indent_next_) { - for (size_t i = 0; i < count_; ++i) { - int_type r = out_sbuf_->sputc(text_); - if (UNLIKELY(r != text_)) { - out_sbuf_->pubsync(); - r = out_sbuf_->sputc(text_); - CHECK_EQ(r, text_) << "Error writing to buffer. Disk full?"; - } - } - } + char data[1] = { static_cast(c) }; + Write(data, 1u); indent_next_ = (c == '\n'); - int_type r = out_sbuf_->sputc(c); - if (UNLIKELY(r != c)) { - out_sbuf_->pubsync(); - r = out_sbuf_->sputc(c); - CHECK_EQ(r, c) << "Error writing to buffer. Disk full?"; - } - return r; + return c; } int sync() { return out_sbuf_->pubsync(); } + void Write(const char* s, std::streamsize n) { + if (indent_next_) { + size_t remaining = count_; + while (remaining != 0u) { + size_t to_write = std::min(remaining, sizeof(text_)); + RawWrite(text_, to_write); + remaining -= to_write; + } + indent_next_ = false; + } + RawWrite(s, n); + } + + void RawWrite(const char* s, std::streamsize n) { + size_t written = out_sbuf_->sputn(s, n); + s += written; + n -= written; + while (n != 0u) { + out_sbuf_->pubsync(); + written = out_sbuf_->sputn(s, n); + CHECK_NE(written, 0u) << "Error writing to buffer. Disk full?"; + s += written; + n -= written; + } + } + bool indent_next_; // Buffer to write output to. std::streambuf* const out_sbuf_; // Text output as indent. - const char text_; + const char text_[8]; // Number of times text is output. const size_t count_; -- 2.11.0