30 #include "third_party/jsoncpp/include/json/json.h"
57 static uint32 UpToNearestFour(uint32 n) {
61 return n + (4 - (n % 4));
75 virtual uint32 GetRawSizeInBytes()
const = 0;
77 virtual void AppendToString(std::string* output)
const = 0;
82 uint32 GetAlignedSizeInBytes()
const {
83 return UpToNearestFour(GetRawSizeInBytes());
103 void AddPart(uint32
type, Part* part) {
108 info.length = part->GetRawSizeInBytes();
110 for (
size_t i = 0; i <
parts.size(); i++) {
111 info.offset +=
parts[i]->GetAlignedSizeInBytes();
114 parts.push_back(part);
117 void AppendToString(uint32
id, uint32 type, std::string* output) {
121 info.part_count =
static_cast<uint32
>(
parts.size());
124 info.length =
static_cast<uint32
>(
sizeof(ChunkInfo)) +
125 static_cast<uint32
>(
sizeof(PartInfo)) * info.part_count;
126 for (
size_t i = 0; i <
parts.size(); i++) {
127 info.length +=
parts[i]->GetAlignedSizeInBytes();
129 info.start_time = -1;
136 for (
size_t i = 0; i <
parts.size(); i++) {
137 parts[i]->AppendToString(output);
145 class StringTable :
public Part {
150 explicit StringTable(
bool include_null)
153 void AddString(
const std::string&
str) {
155 for (
size_t i = 0; i < split.size(); ++i) {
156 table_.push_back(split[i]);
160 uint32 GetRawSizeInBytes()
const override {
161 size_t raw_size_in_bytes = 0;
162 for (
size_t i = 0; i <
table_.size(); ++i) {
163 const size_t string_length =
table_[i].length();
165 raw_size_in_bytes += string_length + 1;
167 raw_size_in_bytes += string_length;
170 return static_cast<uint32
>(raw_size_in_bytes);
173 uint32 GetTableSize()
const {
return static_cast<uint32
>(
table_.size()); }
175 void AppendToString(std::string* output)
const override {
176 for (
size_t i = 0; i <
table_.size(); ++i) {
177 output->append(
table_[i]);
187 uint32 extra = GetAlignedSizeInBytes() - GetRawSizeInBytes();
188 for (uint32 i = 0; i < extra; ++i) {
194 std::vector<std::string>* GetMutableTable() {
return &
table_; }
201 struct EventBuffer :
public Part {
203 uint32 GetRawSizeInBytes()
const override {
204 return static_cast<uint32
>(
buffer.length());
207 void AppendToString(std::string* output)
const override {
217 : recorder_(recorder) {
228 : recorder_(recorder) {
239 : trace_recorder_(GetAllocator()),
240 named_trace_recorders_(GetAllocator()),
241 recorder_list_(GetAllocator()),
243 scope_event_map_(GetAllocator()),
244 reverse_scope_event_map_(GetAllocator()) {
248 : trace_recorder_(GetAllocator()),
249 named_trace_recorders_(GetAllocator()),
250 recorder_list_(GetAllocator()),
251 buffer_size_(buffer_size),
252 scope_event_map_(GetAllocator()),
253 reverse_scope_event_map_(GetAllocator()) {
259 if (!timeline_metrics_.empty()) {
265 for (
size_t i = 0; i < recorder_list_.size(); ++i) {
266 delete recorder_list_[i];
267 recorder_list_[i] = NULL;
277 *recorder = AllocateTraceRecorder();
285 NamedTraceRecorderArray* recorders = named_trace_recorders_.
Get();
290 recorder = AllocateTraceRecorder();
299 LOG(
WARNING) <<
"Unknown name(" << name <<
") for named TraceRecorder.";
301 recorders->recorders[
name] = recorder;
307 if (buffer_size_ == 0) {
310 recorder =
new (
GetAllocator()) TraceRecorder(
this, buffer_size_);
314 recorder_list_.push_back(recorder);
322 ScopeEventMap::const_iterator it = scope_event_map_.find(string_id);
323 if (it != scope_event_map_.end()) {
327 const int new_event_id =
329 scope_event_map_.insert(
330 std::make_pair(static_cast<const void*>(string_id), new_event_id));
331 reverse_scope_event_map_.insert(std::make_pair(new_event_id, string_id));
336 return reverse_scope_event_map_.at(event_id);
343 static const int kBuiltinEventArgNum[] = {
344 0, 5, 0, 4, 1, 1, 1, 0, 0, 2, 2, 2, 3, 1, 1, 1, 1, 1};
348 return kBuiltinEventArgNum[event_id];
352 uint32 event_id,
int arg_index) {
357 static const int kOffsetTable[] = {
358 0, 1, 6, 7, 11, 12, 13, 14, 15, 16, 18, 20, 22, 25, 26, 27, 28, 29};
383 return kBuiltinEventArgTypes[kOffsetTable[event_id] + arg_index];
389 static const uint32 magic_number = 0xdeadbeef;
390 static const uint32 wtf_version = 0xe8214400;
391 static const uint32 format_version = 10;
398 Json::Value flags(Json::arrayValue);
399 flags.append(
"has_high_resolution_times");
403 Json::Value icon(Json::objectValue);
404 icon[
"uri"] =
"https://maps.gstatic.com/favicon3.ico";
408 Json::Value agent(Json::objectValue);
409 agent[
"device"] =
"Ion";
410 agent[
"platform"] =
"SomePlatform";
411 agent[
"platformVersion"] =
"";
415 Json::Value context(Json::objectValue);
416 context[
"args"] = Json::Value(Json::arrayValue);
417 context[
"contextType"] =
"script";
418 context[
"icon"] = icon;
419 context[
"taskId"] =
"";
420 context[
"title"] =
"Ion";
422 context[
"userAgent"] = agent;
425 json[
"type"] =
"file_header";
426 json[
"flags"] = flags;
428 json[
"timebase"] = 1412611454780.701;
429 json[
"contextInfo"] = context;
431 Json::FastWriter json_writer;
432 std::string json_string = json_writer.write(json);
433 StringTable file_header_table(
false);
434 file_header_table.AddString(json_string);
437 file_header.AddPart(0x10000, &file_header_table);
438 file_header.AppendToString(2, 0x1, &output);
441 StringTable def_table;
444 "uint16 wireId, uint16 eventClass, uint32 flags, ascii name, ascii args\n"
445 "wtf.trace#discontinuity\n"
447 "uint16 zoneId, ascii name, ascii type, ascii location\n"
454 "wtf.scope#enterTracing\n"
456 "wtf.scope#appendData\n"
457 "ascii name, any value\n"
459 "ascii name, any value\n"
460 "wtf.trace#timeStamp\n"
461 "ascii name, any value\n"
462 "wtf.timeRange#begin\n"
463 "uint32 id, ascii name, any value\n"
464 "wtf.timeRange#end\n"
466 "wtf.timing#frameStart\n"
468 "wtf.timing#frameEnd\n"
470 "wtf.scope#appendData_url_utf8\n"
472 "wtf.scope#appendData_readyState_int32\n"
476 const uint32 event_string_offset = def_table.GetTableSize();
477 for (ScopeEventMap::const_iterator it = scope_event_map_.begin();
478 it != scope_event_map_.end(); ++it) {
479 def_table.AddString(reinterpret_cast<const char*>(it->first));
503 EventBuffer def_events;
505 std::string* event_buffer = &def_events.buffer;
507 1, 0, 1, 0, 40, 0, 1,
508 1, 0, 2, 0, 32, 2, 0xffffffff,
509 1, 0, 3, 0, 40, 3, 4,
510 1, 0, 4, 0, 40, 5, 6,
511 1, 0, 5, 0, 40, 7, 8,
512 1, 0, 6, 1, 32, 9, 10,
513 1, 0, 7, 1, 44, 11, 0xffffffff,
514 1, 0, 8, 0, 40, 12, 0xffffffff,
515 1, 0, 9, 0, 56, 13, 14,
516 1, 0, 10, 0, 40, 15, 16,
517 1, 0, 11, 0, 32, 17, 18,
518 1, 0, 12, 0, 40, 19, 20,
519 1, 0, 13, 0, 40, 21, 22,
520 1, 0, 14, 0, 8, 23, 24,
521 1, 0, 15, 0, 8, 25, 26,
522 1, 0, 16, 0, 24, 27, 28,
523 1, 0, 17, 0, 24, 29, 30
529 int event_counter = 0;
531 for (ScopeEventMap::const_iterator it = scope_event_map_.begin();
532 it != scope_event_map_.end(); ++it) {
543 temp = event_string_offset + event_counter;
552 Chunk events_defined;
553 events_defined.AddPart(0x30000, &def_table);
554 events_defined.AddPart(0x20002, &def_events);
555 events_defined.AppendToString(3, 0x2, &output);
558 const int num_trace_threads =
static_cast<int>(recorder_list_.size());
560 table.AddString(
"script");
561 table.AddString(
"Some_Location");
562 for (
int chunk_i = 0; chunk_i < num_trace_threads; ++chunk_i) {
563 const int zone_id = chunk_i + 1;
565 table.AddString(location_string);
570 std::string* event_buffer = &events.buffer;
571 for (
int chunk_i = 0; chunk_i < num_trace_threads; ++chunk_i) {
572 const int zone_id = chunk_i + 1;
590 for (
int chunk_i = 0; chunk_i < num_trace_threads; ++chunk_i) {
592 const int zone_id = chunk_i + 1;
604 rec->
DumpTrace(event_buffer, table.GetTableSize());
612 trace.AddPart(0x30000, &table);
613 trace.AddPart(0x20002, &events);
614 trace.AppendToString(1, 0x2, &output);
620 if (!filename.empty()) {
621 LOG(
INFO) <<
"Writing current WTF traces to: " << filename;
622 std::ofstream filestream(
623 filename.c_str(), std::ios::out | std::ios::binary);
624 if (filestream.good()) {
629 <<
" for writing WTF traces.";
635 std::unique_ptr<TimelineNode> root(
new TimelineNode(
"root"));
636 for (
const auto recorder : recorder_list_) {
637 std::unique_ptr<TimelineThread> thread(
649 for (
const auto& metric : timeline_metrics_)
650 metric->Run(timeline, &benchmark);
The event for defining new WTF events, both custom and built-in events.
static int GetNumArgsForEvent(uint32 event_id)
Gets the number of arguments for a particular event.
std::vector< Part * > parts
Class for recording frame events.
void SetThreadName(const std::string &name)
Sets a name for the thread that this recorder is tracing.
Copyright 2016 Google Inc.
GenericLockGuard< port::Mutex > LockGuard
Convenient typedefs for ion::port::Mutex.
void AddChild(std::unique_ptr< TimelineNode > child)
Add a node to the children. It becomes the last child.
#define LOG(severity)
Logs the streamed message unconditionally with a severity of severity.
static EventArgType GetArgType(uint32 event_id, int arg_index)
Gets the argument types for a particular event.
std::vector< std::string > ION_API SplitString(const std::string &str, const std::string &delimiters)
Splits a string into a vector of substrings, given a set of delimiter characters (expressed as a stri...
Copyright 2016 Google Inc.
~CallTraceManager() override
void AddTraceToTimelineNode(TimelineNode *root) const
Adds all events in the trace as a sub-tree under the passed in root node.
void WriteFile(const std::string &filename) const
Writes the current WTF trace to a file, which usually ends in the extension ".wtf-trace".
void LeaveScope()
Leaves the current (most recent) scope.
A LockGuard locks a mutex when created, and unlocks it when destroyed.
std::string ValueToString(const T &val)
ValueToString.
NamedTraceRecorderType
Defines name trace recorders.
void AppendBytes(std::string *s, const T &value)
Convenience method to append bytes to string.
void DumpStrings(std::vector< std::string > *table) const
Dumps the strings one by one to a string table.
EventArgType
Defines argument types for WTF events.
void LeaveFrame()
Records a frame exit event for the current frame index.
Copyright 2016 Google Inc.
std::vector< std::string > table_
void OutputBenchmarkPretty(const std::string &id_string, bool print_descriptions, const Benchmark &benchmark, std::ostream &out)
Outputs benchmark results in pretty format.
void EnterScope(int event_id)
Queries and records the event corresponding to the provided event_id.
void DumpTrace(std::string *output, uint32 string_index_offset) const
Appends a binary dump of the trace to the output string.
void EnterFrame(uint32 frame_number)
Records a frame enter event with a specified frame index.
std::string SnapshotCallTraces() const
Returns a snapshot of traces to a string in binary .wtf-trace format.
TraceRecorder * GetNamedTraceRecorder(NamedTraceRecorderType name)
Gets the TraceRecorder instance specific to the current thread of the given name. ...
analytics::Benchmark RunTimelineMetrics() const
Runs all registered metrics on the current timeline and returns a benchmark object containing the col...
ScopedFrameTracer(TraceRecorder *recorder, uint32 id)
T * Get()
Returns a T instance for the current thread, creating it first if necessary.
std::vector< PartInfo > part_headers
Events for managing zones.
TraceRecorder * GetTraceRecorder()
Gets the TraceRecorder instance specific to the current thread.
const ion::port::ThreadId & GetThreadId() const
Returns the ID of the thread that this recorder is tracing.
size_t GetNumScopeEvents() const
Returns the number of unique custom scope events recorded.
The starting offset for scope event ids, purposefully set high to make room for built-in WTF events...
std::string GetThreadName() const
Returns the name for the thread that this recorder is tracing.
int GetScopeEnterEvent(const char *string_id)
Queries the event id of a scope enter event, based on string_id.
The Benchmark class provides types and utilities to make it easier to create performance benchmarks...
ScopedTracer(TraceRecorder *recorder, int id)
const AllocatorPtr & GetAllocator() const
Returns the Allocator that was used for the instance.
void * GetThreadLocalStorage(ThreadLocalStorageKey key)
Returns the pointer to the thread-local storage area indicated by key.
Timeline BuildTimeline() const
Convert the current WTF trace into a timeline.
const char * GetScopeEnterEventName(uint32 event_id) const
Returns the name of the scope enter event with the given id.