| 88 | } |
| 89 | |
| 90 | void ChromeTraceFormatter::EmitCounter( |
| 91 | const string& category, const string& name, int64 pid, int64 ts, |
| 92 | const string& device, int64 bytes, |
| 93 | const std::map<int64, std::vector<string>>& tensor_mem) { |
| 94 | Json::Value event = CreateEvent("C", category, "Allocated Bytes", pid, 0, ts); |
| 95 | Json::Value args(Json::objectValue); |
| 96 | args["Allocator Bytes in Use"] = Json::Int64(bytes); |
| 97 | event["args"] = args; |
| 98 | events_.push_back(event); |
| 99 | |
| 100 | // TODO(xpan): chrome://tracing is not ideal visualization for memory. |
| 101 | // It would be great to have a customized UI for it. |
| 102 | Json::Value event2 = |
| 103 | CreateEvent("C", category, "Top Allocations", pid + 1, 0, ts); |
| 104 | Json::Value args2(Json::objectValue); |
| 105 | // Need to reserve the same args for all locations. |
| 106 | for (int i = 1; i < kMaxDisplayedMemNode; ++i) { |
| 107 | args2[strings::Printf("Top Allocation %02d", i)] = Json::Value("N/A"); |
| 108 | } |
| 109 | int count = 0; |
| 110 | for (auto it = tensor_mem.rbegin(); it != tensor_mem.rend(); ++it) { |
| 111 | for (const string& t : it->second) { |
| 112 | if (bytes < it->first || count >= kMaxDisplayedMemNode) { |
| 113 | break; |
| 114 | } |
| 115 | args2[strings::Printf("Top Allocation %02d", count)] = |
| 116 | Json::Value(strings::StrCat(it->first / 1000000.0, " MB from ", t)); |
| 117 | ++count; |
| 118 | bytes -= it->first; |
| 119 | } |
| 120 | } |
| 121 | args2[strings::StrCat("Not Displayed")] = |
| 122 | Json::Value(strings::Printf("%.2f MB", bytes / 1000000.0)); |
| 123 | event2["args"] = args2; |
| 124 | events_.push_back(event2); |
| 125 | } |
| 126 | |
| 127 | string ChromeTraceFormatter::Format() { |
| 128 | Json::Value trace; |