From e48c3534cc28ce22e6924a6ffdecb1af2f564045 Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Sun, 6 Sep 2015 10:28:17 -0700 Subject: [PATCH] Removing copy to temp buffer in log flush. --- src/xenia/base/logging.cc | 19 ++++++++++++++++--- src/xenia/base/ring_buffer.cc | 22 ++++++++++++++++++++++ src/xenia/base/ring_buffer.h | 9 +++++++++ 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/xenia/base/logging.cc b/src/xenia/base/logging.cc index d37ac4299..1e9f6d205 100644 --- a/src/xenia/base/logging.cc +++ b/src/xenia/base/logging.cc @@ -104,9 +104,10 @@ class Logger { bool did_write = false; while (!ring_buffer_.empty()) { did_write = true; + + // Read line header and write out the line prefix. LogLine line; ring_buffer_.Read(&line, sizeof(line)); - ring_buffer_.Read(log_format_buffer_.data(), line.buffer_length); char prefix[] = { line.level_char, '>', @@ -125,11 +126,23 @@ class Logger { std::snprintf(prefix + 3, sizeof(prefix) - 3, "%08" PRIX32 " ", line.thread_id); fwrite(prefix, 1, sizeof(prefix) - 1, file_); - fwrite(log_format_buffer_.data(), 1, line.buffer_length, file_); - if (log_format_buffer_[line.buffer_length - 1] != '\n') { + + // Get access to the line data - which may be split in the ring buffer - + // and write it out in parts. + auto line_range = ring_buffer_.BeginRead(line.buffer_length); + fwrite(line_range.first, 1, line_range.first_length, file_); + if (line_range.second_length) { + fwrite(line_range.second, 1, line_range.second_length, file_); + } + // Always ensure there is a newline. + char last_char = line_range.second + ? line_range.second[line_range.second_length - 1] + : line_range.first[line_range.first_length - 1]; + if (last_char != '\n') { const char suffix[1] = {'\n'}; fwrite(suffix, 1, sizeof(suffix), file_); } + ring_buffer_.EndRead(std::move(line_range)); } mutex_.unlock(); if (did_write) { diff --git a/src/xenia/base/ring_buffer.cc b/src/xenia/base/ring_buffer.cc index 13f727377..05215ec10 100644 --- a/src/xenia/base/ring_buffer.cc +++ b/src/xenia/base/ring_buffer.cc @@ -17,6 +17,28 @@ namespace xe { RingBuffer::RingBuffer(uint8_t* buffer, size_t capacity) : buffer_(buffer), capacity_(capacity) {} +RingBuffer::ReadRange RingBuffer::BeginRead(size_t count) { + count = std::min(count, capacity_); + if (!count) { + return {0}; + } + if (read_offset_ + count < capacity_) { + return {buffer_ + read_offset_, count, nullptr, 0}; + } else { + size_t left_half = capacity_ - read_offset_; + size_t right_half = count - left_half; + return {buffer_ + read_offset_, left_half, buffer_, right_half}; + } +} + +void RingBuffer::EndRead(ReadRange read_range) { + if (read_range.second_length) { + read_offset_ = read_range.second_length; + } else { + read_offset_ += read_range.first_length; + } +} + size_t RingBuffer::Read(uint8_t* buffer, size_t count) { count = std::min(count, capacity_); if (!count) { diff --git a/src/xenia/base/ring_buffer.h b/src/xenia/base/ring_buffer.h index abe07ff53..9628c9c0c 100644 --- a/src/xenia/base/ring_buffer.h +++ b/src/xenia/base/ring_buffer.h @@ -48,6 +48,15 @@ class RingBuffer { } } + struct ReadRange { + const uint8_t* first; + size_t first_length; + const uint8_t* second; + size_t second_length; + }; + ReadRange BeginRead(size_t count); + void EndRead(ReadRange read_range); + size_t Read(uint8_t* buffer, size_t count); template size_t Read(T* buffer, size_t count) {