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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 120
121 121
122 bool Log::is_stopped_ = false; 122 bool Log::is_stopped_ = false;
123 Log::WritePtr Log::Write = NULL; 123 Log::WritePtr Log::Write = NULL;
124 FILE* Log::output_handle_ = NULL; 124 FILE* Log::output_handle_ = NULL;
125 LogDynamicBuffer* Log::output_buffer_ = NULL; 125 LogDynamicBuffer* Log::output_buffer_ = NULL;
126 // Must be the same message as in Logger::PauseProfiler 126 // Must be the same message as in Logger::PauseProfiler
127 const char* Log::kDynamicBufferSeal = "profiler,\"pause\"\n"; 127 const char* Log::kDynamicBufferSeal = "profiler,\"pause\"\n";
128 Mutex* Log::mutex_ = NULL; 128 Mutex* Log::mutex_ = NULL;
129 char* Log::message_buffer_ = NULL; 129 char* Log::message_buffer_ = NULL;
130 LogRecordCompressor* Log::record_compressor_ = NULL;
130 131
131 132
132 void Log::Init() { 133 void Log::Init() {
133 mutex_ = OS::CreateMutex(); 134 mutex_ = OS::CreateMutex();
134 message_buffer_ = NewArray<char>(kMessageBufferSize); 135 message_buffer_ = NewArray<char>(kMessageBufferSize);
136 if (FLAG_compress_log) {
137 record_compressor_ = new LogRecordCompressor(kRecordCompressorWindow);
138 }
135 } 139 }
136 140
137 141
138 void Log::OpenStdout() { 142 void Log::OpenStdout() {
139 ASSERT(!IsEnabled()); 143 ASSERT(!IsEnabled());
140 output_handle_ = stdout; 144 output_handle_ = stdout;
141 Write = WriteToFile; 145 Write = WriteToFile;
142 Init(); 146 Init();
143 } 147 }
144 148
(...skipping 21 matching lines...) Expand all
166 fclose(output_handle_); 170 fclose(output_handle_);
167 output_handle_ = NULL; 171 output_handle_ = NULL;
168 } else if (Write == WriteToMemory) { 172 } else if (Write == WriteToMemory) {
169 delete output_buffer_; 173 delete output_buffer_;
170 output_buffer_ = NULL; 174 output_buffer_ = NULL;
171 } else { 175 } else {
172 ASSERT(Write == NULL); 176 ASSERT(Write == NULL);
173 } 177 }
174 Write = NULL; 178 Write = NULL;
175 179
180 delete record_compressor_;
181 record_compressor_ = NULL;
182
183 DeleteArray(message_buffer_);
184 message_buffer_ = NULL;
185
176 delete mutex_; 186 delete mutex_;
177 mutex_ = NULL; 187 mutex_ = NULL;
178 188
179 is_stopped_ = false; 189 is_stopped_ = false;
180 } 190 }
181 191
182 192
183 int Log::GetLogLines(int from_pos, char* dest_buf, int max_size) { 193 int Log::GetLogLines(int from_pos, char* dest_buf, int max_size) {
184 if (Write != WriteToMemory) return 0; 194 if (Write != WriteToMemory) return 0;
185 ASSERT(output_buffer_ != NULL); 195 ASSERT(output_buffer_ != NULL);
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 Append("\\,"); 283 Append("\\,");
274 } else if (c == '\\') { 284 } else if (c == '\\') {
275 Append("\\\\"); 285 Append("\\\\");
276 } else { 286 } else {
277 Append("%lc", c); 287 Append("%lc", c);
278 } 288 }
279 } 289 }
280 } 290 }
281 291
282 292
293 bool LogMessageBuilder::StoreInCompressor() {
294 if (!FLAG_compress_log) return true;
295 ASSERT(Log::record_compressor_ != NULL);
296 return Log::record_compressor_->Store(
297 Vector<const char>(Log::message_buffer_, pos_));
298 }
299
300
301 bool LogMessageBuilder::RetrieveCompressedPrevious(const char* prefix) {
302 if (!FLAG_compress_log) return true;
303 ASSERT(Log::record_compressor_ != NULL);
304 pos_ = 0;
305 if (prefix[0] != '\0') Append(prefix);
306 Vector<char> prev_record(Log::message_buffer_ + pos_,
307 Log::kMessageBufferSize - pos_);
308 const bool has_previous =
309 Log::record_compressor_->RetrievePreviousCompressed(&prev_record);
310 if (!has_previous) return false;
311 pos_ += prev_record.length();
312 return true;
313 }
314
315
283 void LogMessageBuilder::WriteToLogFile() { 316 void LogMessageBuilder::WriteToLogFile() {
284 ASSERT(pos_ <= Log::kMessageBufferSize); 317 ASSERT(pos_ <= Log::kMessageBufferSize);
285 const int written = Log::Write(Log::message_buffer_, pos_); 318 const int written = Log::Write(Log::message_buffer_, pos_);
286 if (written != pos_ && write_failure_handler != NULL) { 319 if (written != pos_ && write_failure_handler != NULL) {
287 write_failure_handler(); 320 write_failure_handler();
288 } 321 }
289 } 322 }
290 323
291 324
292 void LogMessageBuilder::WriteCStringToLogFile(const char* str) { 325 void LogMessageBuilder::WriteCStringToLogFile(const char* str) {
293 const int len = strlen(str); 326 const int len = strlen(str);
294 const int written = Log::Write(str, len); 327 const int written = Log::Write(str, len);
295 if (written != len && write_failure_handler != NULL) { 328 if (written != len && write_failure_handler != NULL) {
296 write_failure_handler(); 329 write_failure_handler();
297 } 330 }
298 } 331 }
299 332
333
334 // Formatting string for back references. E.g. "#2:4" means
335 // "the second line above, start from the 4th field (0-based)".
336 const char* LogRecordCompressor::kBackwardReferenceFormat = "#%d:%d";
337
338
339 LogRecordCompressor::~LogRecordCompressor() {
340 for (int i = 0; i < buffer_.length(); ++i) {
341 buffer_[i].Dispose();
342 }
343 }
344
345
346 bool LogRecordCompressor::Store(const Vector<const char>& record) {
347 // Check if the record is the same as the last stored one.
348 if (curr_ != -1) {
349 Vector<const char>& curr = buffer_[curr_];
350 if (record.length() == curr.length()
351 && strncmp(record.start(), curr.start(), record.length()) == 0) {
352 return false;
353 }
354 }
355 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.
356 curr_ %= buffer_.length();
357 Vector<char> record_copy = Vector<char>::New(record.length());
358 memcpy(record_copy.start(), record.start(), record.length());
359 buffer_[curr_].Dispose();
360 buffer_[curr_] =
361 Vector<const char>(record_copy.start(), record_copy.length());
362 return true;
363 }
364
365
366 bool LogRecordCompressor::RetrievePreviousCompressed(
367 Vector<char>* prev_record) {
368 if (prev_ == -1) return false;
369
370 int index = prev_;
371 // Distance from prev_.
372 int distance = 0;
373 // Best compression result among records in the buffer.
374 struct {
375 intptr_t truncated_len;
376 int distance;
377 int field_num;
378 } best = {-1, 0, 0};
379 Vector<const char>& prev = buffer_[prev_];
380 const char* const prev_end = prev.start() + prev.length();
381 do {
382 // We're moving backwards until we reach the current record.
383 if (--index == -1) index = buffer_.length() - 1;
384 ++distance;
385 if (index == curr_) break;
386
387 Vector<const char>& data = buffer_[index];
388 if (data.start() == NULL) break;
389 const char* const data_end = data.start() + data.length();
390 const char* prev_ptr = prev_end;
391 const char* data_ptr = data_end;
392 // 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
393 while (prev_ptr != prev.start() && data_ptr != data.start()
394 && *(prev_ptr - 1) == *(data_ptr - 1)) {
395 --prev_ptr;
396 --data_ptr;
397 }
398 if (prev_end - prev_ptr < kUncompressibleBound) continue;
399
400 // Align to the field boundary.
401 do {
402 ++prev_ptr;
403 ++data_ptr;
404 } while (prev_ptr != prev_end
405 && (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
406 || data_ptr != data.start()
407 && *(data_ptr - 1) != kFieldSeparator));
408 // Check if the record is still compressible.
409 const intptr_t truncated_len = prev_end - prev_ptr;
410 if (truncated_len < kUncompressibleBound) continue;
411
412 // Determine reference field number.
413 int field_num = 0;
414 for (const char* fld_ptr = data.start();
415 fld_ptr != data_ptr; ++fld_ptr) {
416 if (*fld_ptr == kFieldSeparator) field_num++;
417 }
418 // Record compression results.
419 if (truncated_len > best.truncated_len) {
420 best.truncated_len = truncated_len;
421 best.distance = distance;
422 best.field_num = field_num;
423 }
424 } while (true);
425
426 if (best.distance == 0) {
427 // Can't compress the previous record. Return as is.
428 ASSERT(prev_record->length() >= prev.length());
429 memcpy(prev_record->start(), prev.start(), prev.length());
430 prev_record->Truncate(prev.length());
431 } else {
432 // Copy the uncompressible part unchanged.
433 const intptr_t unchanged_len = prev.length() - best.truncated_len;
434 ASSERT(prev_record->length() >= unchanged_len + kUncompressibleBound);
435 memcpy(prev_record->start(), prev.start(), unchanged_len);
436 // Append the backward reference.
437 Vector<char> patch(prev_record->start() + unchanged_len,
438 kUncompressibleBound);
439 OS::SNPrintF(patch, kBackwardReferenceFormat,
440 best.distance, best.field_num);
441 prev_record->Truncate(unchanged_len + strlen(patch.start()));
442 }
443 return true;
444 }
445
300 #endif // ENABLE_LOGGING_AND_PROFILING 446 #endif // ENABLE_LOGGING_AND_PROFILING
301 447
302 } } // namespace v8::internal 448 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698