Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(736)

Unified Diff: src/log-utils.cc

Issue 123012: Implement tick events compression in a log file. (Closed)
Patch Set: Created 11 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/log-utils.cc
diff --git a/src/log-utils.cc b/src/log-utils.cc
index 43610497ef6382e72b3b73b9d68f8fa5781fa061..b0d7159df082d9a92944c2dec39c4b7ecd3d0702 100644
--- a/src/log-utils.cc
+++ b/src/log-utils.cc
@@ -127,11 +127,15 @@ LogDynamicBuffer* Log::output_buffer_ = NULL;
const char* Log::kDynamicBufferSeal = "profiler,\"pause\"\n";
Mutex* Log::mutex_ = NULL;
char* Log::message_buffer_ = NULL;
+LogRecordCompressor* Log::record_compressor_ = NULL;
void Log::Init() {
mutex_ = OS::CreateMutex();
message_buffer_ = NewArray<char>(kMessageBufferSize);
+ if (FLAG_compress_log) {
+ record_compressor_ = new LogRecordCompressor(kRecordCompressorWindow);
+ }
}
@@ -173,6 +177,12 @@ void Log::Close() {
}
Write = NULL;
+ delete record_compressor_;
+ record_compressor_ = NULL;
+
+ DeleteArray(message_buffer_);
+ message_buffer_ = NULL;
+
delete mutex_;
mutex_ = NULL;
@@ -280,6 +290,29 @@ void LogMessageBuilder::AppendDetailed(String* str, bool show_impl_info) {
}
+bool LogMessageBuilder::StoreInCompressor() {
+ if (!FLAG_compress_log) return true;
+ ASSERT(Log::record_compressor_ != NULL);
+ return Log::record_compressor_->Store(
+ Vector<const char>(Log::message_buffer_, pos_));
+}
+
+
+bool LogMessageBuilder::RetrieveCompressedPrevious(const char* prefix) {
+ if (!FLAG_compress_log) return true;
+ ASSERT(Log::record_compressor_ != NULL);
+ pos_ = 0;
+ if (prefix[0] != '\0') Append(prefix);
+ Vector<char> prev_record(Log::message_buffer_ + pos_,
+ Log::kMessageBufferSize - pos_);
+ const bool has_previous =
+ Log::record_compressor_->RetrievePreviousCompressed(&prev_record);
+ if (!has_previous) return false;
+ pos_ += prev_record.length();
+ return true;
+}
+
+
void LogMessageBuilder::WriteToLogFile() {
ASSERT(pos_ <= Log::kMessageBufferSize);
const int written = Log::Write(Log::message_buffer_, pos_);
@@ -297,6 +330,119 @@ void LogMessageBuilder::WriteCStringToLogFile(const char* str) {
}
}
+
+// Formatting string for back references. E.g. "#2:4" means
+// "the second line above, start from the 4th field (0-based)".
+const char* LogRecordCompressor::kBackwardReferenceFormat = "#%d:%d";
+
+
+LogRecordCompressor::~LogRecordCompressor() {
+ for (int i = 0; i < buffer_.length(); ++i) {
+ buffer_[i].Dispose();
+ }
+}
+
+
+bool LogRecordCompressor::Store(const Vector<const char>& record) {
+ // Check if the record is the same as the last stored one.
+ if (curr_ != -1) {
+ Vector<const char>& curr = buffer_[curr_];
+ if (record.length() == curr.length()
+ && strncmp(record.start(), curr.start(), record.length()) == 0) {
+ return false;
+ }
+ }
+ prev_ = curr_++;
Søren Thygesen Gjesse 2009/06/11 11:13:56 Maybe add a comment here saying that we keep a cir
Mikhail Naganov 2009/06/11 14:07:12 Done.
+ curr_ %= buffer_.length();
+ Vector<char> record_copy = Vector<char>::New(record.length());
+ memcpy(record_copy.start(), record.start(), record.length());
+ buffer_[curr_].Dispose();
+ buffer_[curr_] =
+ Vector<const char>(record_copy.start(), record_copy.length());
+ return true;
+}
+
+
+bool LogRecordCompressor::RetrievePreviousCompressed(
+ Vector<char>* prev_record) {
+ if (prev_ == -1) return false;
+
+ int index = prev_;
+ // Distance from prev_.
+ int distance = 0;
+ // Best compression result among records in the buffer.
+ struct {
+ intptr_t truncated_len;
+ int distance;
+ int field_num;
+ } best = {-1, 0, 0};
+ Vector<const char>& prev = buffer_[prev_];
+ const char* const prev_end = prev.start() + prev.length();
+ do {
+ // We're moving backwards until we reach the current record.
+ if (--index == -1) index = buffer_.length() - 1;
+ ++distance;
+ if (index == curr_) break;
+
+ Vector<const char>& data = buffer_[index];
+ if (data.start() == NULL) break;
+ const char* const data_end = data.start() + data.length();
+ const char* prev_ptr = prev_end;
+ const char* data_ptr = data_end;
+ // Compare strings backwards, stop on the last matching character.
Søren Thygesen Gjesse 2009/06/11 11:13:56 I am not sure how expensive this is, but perhaps c
Mikhail Naganov 2009/06/11 14:07:12 I'm aware of this optimization, but don't want to
+ while (prev_ptr != prev.start() && data_ptr != data.start()
+ && *(prev_ptr - 1) == *(data_ptr - 1)) {
+ --prev_ptr;
+ --data_ptr;
+ }
+ if (prev_end - prev_ptr < kUncompressibleBound) continue;
+
+ // Align to the field boundary.
+ do {
+ ++prev_ptr;
+ ++data_ptr;
+ } while (prev_ptr != prev_end
+ && (prev_ptr != prev.start() && *(prev_ptr - 1) != kFieldSeparator
Søren Thygesen Gjesse 2009/06/11 11:13:56 Will prev_ptr ever become prev.start() as the do l
Mikhail Naganov 2009/06/11 14:07:12 I've removed field alignment, so this code has gon
+ || data_ptr != data.start()
+ && *(data_ptr - 1) != kFieldSeparator));
+ // Check if the record is still compressible.
+ const intptr_t truncated_len = prev_end - prev_ptr;
+ if (truncated_len < kUncompressibleBound) continue;
+
+ // Determine reference field number.
+ int field_num = 0;
+ for (const char* fld_ptr = data.start();
+ fld_ptr != data_ptr; ++fld_ptr) {
+ if (*fld_ptr == kFieldSeparator) field_num++;
+ }
+ // Record compression results.
+ if (truncated_len > best.truncated_len) {
+ best.truncated_len = truncated_len;
+ best.distance = distance;
+ best.field_num = field_num;
+ }
+ } while (true);
+
+ if (best.distance == 0) {
+ // Can't compress the previous record. Return as is.
+ ASSERT(prev_record->length() >= prev.length());
+ memcpy(prev_record->start(), prev.start(), prev.length());
+ prev_record->Truncate(prev.length());
+ } else {
+ // Copy the uncompressible part unchanged.
+ const intptr_t unchanged_len = prev.length() - best.truncated_len;
+ ASSERT(prev_record->length() >= unchanged_len + kUncompressibleBound);
+ memcpy(prev_record->start(), prev.start(), unchanged_len);
+ // Append the backward reference.
+ Vector<char> patch(prev_record->start() + unchanged_len,
+ kUncompressibleBound);
+ OS::SNPrintF(patch, kBackwardReferenceFormat,
+ best.distance, best.field_num);
+ prev_record->Truncate(unchanged_len + strlen(patch.start()));
+ }
+ return true;
+}
+
#endif // ENABLE_LOGGING_AND_PROFILING
} } // namespace v8::internal

Powered by Google App Engine
This is Rietveld 408576698