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

Side by Side Diff: src/log-utils.cc

Issue 125114: Involve more log compression techniques. (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
« no previous file with comments | « src/log-utils.h ('k') | test/cctest/test-log-utils.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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;
131 // Must be the same as compressed tick event name from Logger.
132 const char* Log::kCompressedTickEventName = "t,";
133 130
134 131
135 void Log::Init() { 132 void Log::Init() {
136 mutex_ = OS::CreateMutex(); 133 mutex_ = OS::CreateMutex();
137 message_buffer_ = NewArray<char>(kMessageBufferSize); 134 message_buffer_ = NewArray<char>(kMessageBufferSize);
138 if (FLAG_compress_log) {
139 record_compressor_ = new LogRecordCompressor(
140 kRecordCompressorWindow, strlen(kCompressedTickEventName));
141 }
142 } 135 }
143 136
144 137
145 void Log::OpenStdout() { 138 void Log::OpenStdout() {
146 ASSERT(!IsEnabled()); 139 ASSERT(!IsEnabled());
147 output_handle_ = stdout; 140 output_handle_ = stdout;
148 Write = WriteToFile; 141 Write = WriteToFile;
149 Init(); 142 Init();
150 } 143 }
151 144
(...skipping 21 matching lines...) Expand all
173 fclose(output_handle_); 166 fclose(output_handle_);
174 output_handle_ = NULL; 167 output_handle_ = NULL;
175 } else if (Write == WriteToMemory) { 168 } else if (Write == WriteToMemory) {
176 delete output_buffer_; 169 delete output_buffer_;
177 output_buffer_ = NULL; 170 output_buffer_ = NULL;
178 } else { 171 } else {
179 ASSERT(Write == NULL); 172 ASSERT(Write == NULL);
180 } 173 }
181 Write = NULL; 174 Write = NULL;
182 175
183 delete record_compressor_;
184 record_compressor_ = NULL;
185
186 DeleteArray(message_buffer_); 176 DeleteArray(message_buffer_);
187 message_buffer_ = NULL; 177 message_buffer_ = NULL;
188 178
189 delete mutex_; 179 delete mutex_;
190 mutex_ = NULL; 180 mutex_ = NULL;
191 181
192 is_stopped_ = false; 182 is_stopped_ = false;
193 } 183 }
194 184
195 185
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
256 246
257 void LogMessageBuilder::Append(String* str) { 247 void LogMessageBuilder::Append(String* str) {
258 AssertNoAllocation no_heap_allocation; // Ensure string stay valid. 248 AssertNoAllocation no_heap_allocation; // Ensure string stay valid.
259 int length = str->length(); 249 int length = str->length();
260 for (int i = 0; i < length; i++) { 250 for (int i = 0; i < length; i++) {
261 Append(static_cast<char>(str->Get(i))); 251 Append(static_cast<char>(str->Get(i)));
262 } 252 }
263 } 253 }
264 254
265 255
256 void LogMessageBuilder::AppendAddress(Address addr) {
257 static Address last_address_ = NULL;
258 AppendAddress(addr, last_address_);
259 last_address_ = addr;
260 }
261
262
263 void LogMessageBuilder::AppendAddress(Address addr, Address bias) {
264 if (!FLAG_compress_log || bias == NULL) {
265 Append("0x%" V8PRIxPTR, addr);
266 } else {
267 intptr_t delta = addr - bias;
268 // To avoid printing negative offsets in an unsigned form,
269 // we are printing an absolute value with a sign.
270 const char sign = delta >= 0 ? '+' : '-';
271 if (sign == '-') { delta = -delta; }
272 Append("%c%" V8PRIxPTR, sign, delta);
273 }
274 }
275
276
266 void LogMessageBuilder::AppendDetailed(String* str, bool show_impl_info) { 277 void LogMessageBuilder::AppendDetailed(String* str, bool show_impl_info) {
267 AssertNoAllocation no_heap_allocation; // Ensure string stay valid. 278 AssertNoAllocation no_heap_allocation; // Ensure string stay valid.
268 int len = str->length(); 279 int len = str->length();
269 if (len > 0x1000) 280 if (len > 0x1000)
270 len = 0x1000; 281 len = 0x1000;
271 if (show_impl_info) { 282 if (show_impl_info) {
272 Append(str->IsAsciiRepresentation() ? 'a' : '2'); 283 Append(str->IsAsciiRepresentation() ? 'a' : '2');
273 if (StringShape(str).IsExternal()) 284 if (StringShape(str).IsExternal())
274 Append('e'); 285 Append('e');
275 if (StringShape(str).IsSymbol()) 286 if (StringShape(str).IsSymbol())
(...skipping 10 matching lines...) Expand all
286 Append("\\,"); 297 Append("\\,");
287 } else if (c == '\\') { 298 } else if (c == '\\') {
288 Append("\\\\"); 299 Append("\\\\");
289 } else { 300 } else {
290 Append("%lc", c); 301 Append("%lc", c);
291 } 302 }
292 } 303 }
293 } 304 }
294 305
295 306
296 bool LogMessageBuilder::StoreInCompressor() { 307 bool LogMessageBuilder::StoreInCompressor(LogRecordCompressor* compressor) {
297 if (!FLAG_compress_log) return true; 308 return compressor->Store(Vector<const char>(Log::message_buffer_, pos_));
298 ASSERT(Log::record_compressor_ != NULL);
299 return Log::record_compressor_->Store(
300 Vector<const char>(Log::message_buffer_, pos_));
301 } 309 }
302 310
303 311
304 bool LogMessageBuilder::RetrieveCompressedPrevious(const char* prefix) { 312 bool LogMessageBuilder::RetrieveCompressedPrevious(
305 if (!FLAG_compress_log) return true; 313 LogRecordCompressor* compressor, const char* prefix) {
306 ASSERT(Log::record_compressor_ != NULL);
307 pos_ = 0; 314 pos_ = 0;
308 if (prefix[0] != '\0') Append(prefix); 315 if (prefix[0] != '\0') Append(prefix);
309 Vector<char> prev_record(Log::message_buffer_ + pos_, 316 Vector<char> prev_record(Log::message_buffer_ + pos_,
310 Log::kMessageBufferSize - pos_); 317 Log::kMessageBufferSize - pos_);
311 const bool has_previous = 318 const bool has_prev = compressor->RetrievePreviousCompressed(&prev_record);
312 Log::record_compressor_->RetrievePreviousCompressed(&prev_record); 319 if (!has_prev) return false;
313 if (!has_previous) return false;
314 pos_ += prev_record.length(); 320 pos_ += prev_record.length();
315 return true; 321 return true;
316 } 322 }
317 323
318 324
319 void LogMessageBuilder::WriteToLogFile() { 325 void LogMessageBuilder::WriteToLogFile() {
320 ASSERT(pos_ <= Log::kMessageBufferSize); 326 ASSERT(pos_ <= Log::kMessageBufferSize);
321 const int written = Log::Write(Log::message_buffer_, pos_); 327 const int written = Log::Write(Log::message_buffer_, pos_);
322 if (written != pos_ && write_failure_handler != NULL) { 328 if (written != pos_ && write_failure_handler != NULL) {
323 write_failure_handler(); 329 write_failure_handler();
324 } 330 }
325 } 331 }
326 332
327 333
328 void LogMessageBuilder::WriteCStringToLogFile(const char* str) { 334 void LogMessageBuilder::WriteCStringToLogFile(const char* str) {
329 const int len = strlen(str); 335 const int len = strlen(str);
330 const int written = Log::Write(str, len); 336 const int written = Log::Write(str, len);
331 if (written != len && write_failure_handler != NULL) { 337 if (written != len && write_failure_handler != NULL) {
332 write_failure_handler(); 338 write_failure_handler();
333 } 339 }
334 } 340 }
335 341
336 342
343 // Formatting string for back references to the whole line. E.g. "#2" means
344 // "the second line above".
345 const char* LogRecordCompressor::kLineBackwardReferenceFormat = "#%d";
346
337 // Formatting string for back references. E.g. "#2:10" means 347 // Formatting string for back references. E.g. "#2:10" means
338 // "the second line above, start from char 10 (0-based)". 348 // "the second line above, start from char 10 (0-based)".
339 const char* LogRecordCompressor::kBackwardReferenceFormat = "#%d:%d"; 349 const char* LogRecordCompressor::kBackwardReferenceFormat = "#%d:%d";
340 350
341 351
342 LogRecordCompressor::~LogRecordCompressor() { 352 LogRecordCompressor::~LogRecordCompressor() {
343 for (int i = 0; i < buffer_.length(); ++i) { 353 for (int i = 0; i < buffer_.length(); ++i) {
344 buffer_[i].Dispose(); 354 buffer_[i].Dispose();
345 } 355 }
346 } 356 }
347 357
348 358
359 static int GetNumberLength(int number) {
360 ASSERT(number >= 0);
361 ASSERT(number < 10000);
362 if (number < 10) return 1;
363 if (number < 100) return 2;
364 if (number < 1000) return 3;
365 return 4;
366 }
367
368
369 int LogRecordCompressor::GetBackwardReferenceSize(int distance, int pos) {
370 // See kLineBackwardReferenceFormat and kBackwardReferenceFormat.
371 return pos == 0 ? GetNumberLength(distance) + 1
372 : GetNumberLength(distance) + GetNumberLength(pos) + 2;
373 }
374
375
376 void LogRecordCompressor::PrintBackwardReference(Vector<char> dest,
377 int distance,
378 int pos) {
379 if (pos == 0) {
380 OS::SNPrintF(dest, kLineBackwardReferenceFormat, distance);
381 } else {
382 OS::SNPrintF(dest, kBackwardReferenceFormat, distance, pos);
383 }
384 }
385
386
349 bool LogRecordCompressor::Store(const Vector<const char>& record) { 387 bool LogRecordCompressor::Store(const Vector<const char>& record) {
350 // Check if the record is the same as the last stored one. 388 // Check if the record is the same as the last stored one.
351 if (curr_ != -1) { 389 if (curr_ != -1) {
352 Vector<const char>& curr = buffer_[curr_]; 390 Vector<const char>& curr = buffer_[curr_];
353 if (record.length() == curr.length() 391 if (record.length() == curr.length()
354 && strncmp(record.start(), curr.start(), record.length()) == 0) { 392 && strncmp(record.start(), curr.start(), record.length()) == 0) {
355 return false; 393 return false;
356 } 394 }
357 } 395 }
358 // buffer_ is circular. 396 // buffer_ is circular.
(...skipping 13 matching lines...) Expand all
372 if (prev_ == -1) return false; 410 if (prev_ == -1) return false;
373 411
374 int index = prev_; 412 int index = prev_;
375 // Distance from prev_. 413 // Distance from prev_.
376 int distance = 0; 414 int distance = 0;
377 // Best compression result among records in the buffer. 415 // Best compression result among records in the buffer.
378 struct { 416 struct {
379 intptr_t truncated_len; 417 intptr_t truncated_len;
380 int distance; 418 int distance;
381 int copy_from_pos; 419 int copy_from_pos;
382 } best = {-1, 0, 0}; 420 int backref_size;
421 } best = {-1, 0, 0, 0};
383 Vector<const char>& prev = buffer_[prev_]; 422 Vector<const char>& prev = buffer_[prev_];
384 const char* const prev_start = prev.start() + start_pos_; 423 const char* const prev_start = prev.start();
385 const char* const prev_end = prev.start() + prev.length(); 424 const char* const prev_end = prev.start() + prev.length();
386 do { 425 do {
387 // We're moving backwards until we reach the current record. 426 // We're moving backwards until we reach the current record.
388 // Remember that buffer_ is circular. 427 // Remember that buffer_ is circular.
389 if (--index == -1) index = buffer_.length() - 1; 428 if (--index == -1) index = buffer_.length() - 1;
390 ++distance; 429 ++distance;
391 if (index == curr_) break; 430 if (index == curr_) break;
392 431
393 Vector<const char>& data = buffer_[index]; 432 Vector<const char>& data = buffer_[index];
394 if (data.start() == NULL) break; 433 if (data.start() == NULL) break;
395 const char* const data_end = data.start() + data.length(); 434 const char* const data_end = data.start() + data.length();
396 const char* prev_ptr = prev_end; 435 const char* prev_ptr = prev_end;
397 const char* data_ptr = data_end; 436 const char* data_ptr = data_end;
398 // Compare strings backwards, stop on the last matching character. 437 // Compare strings backwards, stop on the last matching character.
399 while (prev_ptr != prev_start && data_ptr != data.start() 438 while (prev_ptr != prev_start && data_ptr != data.start()
400 && *(prev_ptr - 1) == *(data_ptr - 1)) { 439 && *(prev_ptr - 1) == *(data_ptr - 1)) {
401 --prev_ptr; 440 --prev_ptr;
402 --data_ptr; 441 --data_ptr;
403 } 442 }
404 const intptr_t truncated_len = prev_end - prev_ptr; 443 const intptr_t truncated_len = prev_end - prev_ptr;
405 if (truncated_len < kUncompressibleBound) continue; 444 const int copy_from_pos = data_ptr - data.start();
445 // Check if the length of compressed tail is enough.
446 if (truncated_len <= kMaxBackwardReferenceSize
447 && truncated_len <= GetBackwardReferenceSize(distance, copy_from_pos)) {
448 continue;
449 }
406 450
407 // Record compression results. 451 // Record compression results.
408 if (truncated_len > best.truncated_len) { 452 if (truncated_len > best.truncated_len) {
409 best.truncated_len = truncated_len; 453 best.truncated_len = truncated_len;
410 best.distance = distance; 454 best.distance = distance;
411 best.copy_from_pos = data_ptr - data.start(); 455 best.copy_from_pos = copy_from_pos;
456 best.backref_size = GetBackwardReferenceSize(distance, copy_from_pos);
412 } 457 }
413 } while (true); 458 } while (true);
414 459
415 if (best.distance == 0) { 460 if (best.distance == 0) {
416 // Can't compress the previous record. Return as is. 461 // Can't compress the previous record. Return as is.
417 ASSERT(prev_record->length() >= prev.length()); 462 ASSERT(prev_record->length() >= prev.length());
418 memcpy(prev_record->start(), prev.start(), prev.length()); 463 memcpy(prev_record->start(), prev.start(), prev.length());
419 prev_record->Truncate(prev.length()); 464 prev_record->Truncate(prev.length());
420 } else { 465 } else {
421 // Copy the uncompressible part unchanged. 466 // Copy the uncompressible part unchanged.
422 const intptr_t unchanged_len = prev.length() - best.truncated_len; 467 const intptr_t unchanged_len = prev.length() - best.truncated_len;
423 ASSERT(prev_record->length() >= unchanged_len + kUncompressibleBound); 468 // + 1 for '\0'.
469 ASSERT(prev_record->length() >= unchanged_len + best.backref_size + 1);
424 memcpy(prev_record->start(), prev.start(), unchanged_len); 470 memcpy(prev_record->start(), prev.start(), unchanged_len);
425 // Append the backward reference. 471 // Append the backward reference.
426 Vector<char> patch(prev_record->start() + unchanged_len, 472 Vector<char> backref(
427 kUncompressibleBound); 473 prev_record->start() + unchanged_len, best.backref_size + 1);
428 OS::SNPrintF(patch, kBackwardReferenceFormat, 474 PrintBackwardReference(backref, best.distance, best.copy_from_pos);
429 best.distance, best.copy_from_pos); 475 ASSERT(strlen(backref.start()) - best.backref_size == 0);
430 prev_record->Truncate(unchanged_len + strlen(patch.start())); 476 prev_record->Truncate(unchanged_len + best.backref_size);
431 } 477 }
432 return true; 478 return true;
433 } 479 }
434 480
435 #endif // ENABLE_LOGGING_AND_PROFILING 481 #endif // ENABLE_LOGGING_AND_PROFILING
436 482
437 } } // namespace v8::internal 483 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/log-utils.h ('k') | test/cctest/test-log-utils.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698