OLD | NEW |
---|---|
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/trace_event/trace_event_argument.h" | 5 #include "base/trace_event/trace_event_argument.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <stack> | |
9 #include <utility> | 10 #include <utility> |
10 | 11 |
11 #include "base/bits.h" | 12 #include "base/bits.h" |
12 #include "base/json/json_writer.h" | 13 #include "base/json/string_escape.h" |
13 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
15 #include "base/trace_event/common/trace_event_common.h" | |
16 #include "base/trace_event/trace_event_impl.h" | |
14 #include "base/trace_event/trace_event_memory_overhead.h" | 17 #include "base/trace_event/trace_event_memory_overhead.h" |
15 #include "base/values.h" | 18 #include "base/values.h" |
16 | 19 |
17 namespace base { | 20 namespace base { |
18 namespace trace_event { | 21 namespace trace_event { |
19 | 22 |
20 namespace { | 23 namespace { |
21 const char kTypeStartDict = '{'; | 24 const char kTypeStartDict = '{'; |
22 const char kTypeEndDict = '}'; | 25 const char kTypeEndDict = '}'; |
23 const char kTypeStartArray = '['; | 26 const char kTypeStartArray = '['; |
24 const char kTypeEndArray = ']'; | 27 const char kTypeEndArray = ']'; |
25 const char kTypeBool = 'b'; | 28 const char kTypeBool = 'b'; |
26 const char kTypeInt = 'i'; | 29 const char kTypeInt = 'i'; |
27 const char kTypeDouble = 'd'; | 30 const char kTypeDouble = 'd'; |
28 const char kTypeString = 's'; | 31 const char kTypeString = 's'; |
29 const char kTypeCStr = '*'; | 32 const char kTypeCStr = '*'; // only used for key names |
30 | 33 |
31 #ifndef NDEBUG | 34 #ifndef NDEBUG |
32 const bool kStackTypeDict = false; | 35 const bool kStackTypeDict = false; |
33 const bool kStackTypeArray = true; | 36 const bool kStackTypeArray = true; |
34 #define DCHECK_CURRENT_CONTAINER_IS(x) DCHECK_EQ(x, nesting_stack_.back()) | 37 #define DCHECK_CURRENT_CONTAINER_IS(x) DCHECK_EQ(x, nesting_stack_.back()) |
35 #define DCHECK_CONTAINER_STACK_DEPTH_EQ(x) DCHECK_EQ(x, nesting_stack_.size()) | 38 #define DCHECK_CONTAINER_STACK_DEPTH_EQ(x) DCHECK_EQ(x, nesting_stack_.size()) |
36 #define DEBUG_PUSH_CONTAINER(x) nesting_stack_.push_back(x) | 39 #define DEBUG_PUSH_CONTAINER(x) nesting_stack_.push_back(x) |
37 #define DEBUG_POP_CONTAINER() nesting_stack_.pop_back() | 40 #define DEBUG_POP_CONTAINER() nesting_stack_.pop_back() |
38 #else | 41 #else |
39 #define DCHECK_CURRENT_CONTAINER_IS(x) do {} while (0) | 42 #define DCHECK_CURRENT_CONTAINER_IS(x) do {} while (0) |
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
447 } | 450 } |
448 } | 451 } |
449 DCHECK(stack.empty()); | 452 DCHECK(stack.empty()); |
450 return std::move(root); | 453 return std::move(root); |
451 } | 454 } |
452 | 455 |
453 void TracedValue::AppendAsTraceFormat(std::string* out) const { | 456 void TracedValue::AppendAsTraceFormat(std::string* out) const { |
454 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); | 457 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); |
455 DCHECK_CONTAINER_STACK_DEPTH_EQ(1u); | 458 DCHECK_CONTAINER_STACK_DEPTH_EQ(1u); |
456 | 459 |
457 // TODO(primiano): this could be smarter, skip the ToBaseValue encoding and | 460 struct State { |
Primiano Tucci (use gerrit)
2017/07/12 15:26:23
isn't this a gcc extension?
DmitrySkiba
2017/07/12 23:48:04
Inner structs? I believe it's valid C++11.
| |
458 // produce the JSON on its own. This will require refactoring JSONWriter | 461 enum Type { kTypeDict, kTypeArray }; |
459 // to decouple the base::Value traversal from the JSON writing bits | 462 Type type; |
460 std::string tmp; | 463 bool needs_comma; |
461 JSONWriter::Write(*ToBaseValue(), &tmp); | 464 }; |
462 *out += tmp; | 465 |
466 auto maybe_append_key_name = [](State current_state, PickleIterator* it, | |
467 std::string* out) { | |
468 if (current_state.type == State::kTypeDict) { | |
469 EscapeJSONString(ReadKeyName(*it), true, out); | |
470 out->append(":"); | |
471 } | |
472 }; | |
473 | |
474 std::stack<State> state_stack; | |
475 | |
476 out->append("{"); | |
Primiano Tucci (use gerrit)
2017/07/12 15:26:23
I think all ths might be even faster if you build
DmitrySkiba
2017/07/12 23:48:04
I don't think there will be a difference - strings
| |
477 state_stack.push({State::kTypeDict}); | |
478 | |
479 PickleIterator it(pickle_); | |
480 for (const char* type; it.ReadBytes(&type, 1);) { | |
481 switch (*type) { | |
482 case kTypeEndDict: | |
483 out->append("}"); | |
484 state_stack.pop(); | |
485 continue; | |
486 | |
487 case kTypeEndArray: | |
488 out->append("]"); | |
489 state_stack.pop(); | |
490 continue; | |
491 } | |
492 | |
493 State& current_state = state_stack.top(); | |
494 if (current_state.needs_comma) { | |
495 out->append(","); | |
496 } | |
497 | |
498 switch (*type) { | |
499 case kTypeStartDict: | |
500 maybe_append_key_name(current_state, &it, out); | |
501 out->append("{"); | |
502 state_stack.push({State::kTypeDict}); | |
503 break; | |
504 | |
505 case kTypeStartArray: | |
506 maybe_append_key_name(current_state, &it, out); | |
507 out->append("["); | |
508 state_stack.push({State::kTypeArray}); | |
509 break; | |
510 | |
511 case kTypeBool: { | |
512 TraceEvent::TraceValue json_value; | |
513 CHECK(it.ReadBool(&json_value.as_bool)); | |
514 maybe_append_key_name(current_state, &it, out); | |
515 TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_BOOL, json_value, out); | |
516 } break; | |
517 | |
518 case kTypeInt: { | |
519 int value; | |
520 CHECK(it.ReadInt(&value)); | |
521 maybe_append_key_name(current_state, &it, out); | |
522 TraceEvent::TraceValue json_value; | |
523 json_value.as_int = value; | |
524 TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_INT, json_value, out); | |
525 } break; | |
526 | |
527 case kTypeDouble: { | |
528 TraceEvent::TraceValue json_value; | |
529 CHECK(it.ReadDouble(&json_value.as_double)); | |
530 maybe_append_key_name(current_state, &it, out); | |
531 TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_DOUBLE, json_value, out); | |
532 } break; | |
533 | |
534 case kTypeString: { | |
535 std::string value; | |
536 CHECK(it.ReadString(&value)); | |
537 maybe_append_key_name(current_state, &it, out); | |
538 TraceEvent::TraceValue json_value; | |
539 json_value.as_string = value.c_str(); | |
540 TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_STRING, json_value, out); | |
541 } break; | |
542 | |
543 default: | |
544 NOTREACHED(); | |
545 } | |
546 | |
547 current_state.needs_comma = true; | |
548 } | |
549 | |
550 out->append("}"); | |
551 state_stack.pop(); | |
552 | |
553 DCHECK(state_stack.empty()); | |
463 } | 554 } |
464 | 555 |
465 void TracedValue::EstimateTraceMemoryOverhead( | 556 void TracedValue::EstimateTraceMemoryOverhead( |
466 TraceEventMemoryOverhead* overhead) { | 557 TraceEventMemoryOverhead* overhead) { |
467 overhead->Add(TraceEventMemoryOverhead::kTracedValue, | 558 overhead->Add(TraceEventMemoryOverhead::kTracedValue, |
468 /* allocated size */ | 559 /* allocated size */ |
469 pickle_.GetTotalAllocatedSize(), | 560 pickle_.GetTotalAllocatedSize(), |
470 /* resident size */ | 561 /* resident size */ |
471 pickle_.size()); | 562 pickle_.size()); |
472 } | 563 } |
473 | 564 |
474 } // namespace trace_event | 565 } // namespace trace_event |
475 } // namespace base | 566 } // namespace base |
OLD | NEW |