168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// found in the LICENSE file.
468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "tools/gn/trace.h"
668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <algorithm>
868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <map>
968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <sstream>
1068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <vector>
1168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
1368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/json/string_escape.h"
1468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/logging.h"
1568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/strings/stringprintf.h"
1668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/synchronization/lock.h"
1768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "tools/gn/filesystem_utils.h"
1868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "tools/gn/label.h"
1968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace {
2168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)class TraceLog {
2368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) public:
2468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  TraceLog() {
2568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    events_.reserve(16384);
2668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
27effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Trace items leaked intentionally.
2868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  void Add(TraceItem* item) {
3068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    base::AutoLock lock(lock_);
3168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    events_.push_back(item);
3268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
3368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Returns a copy for threadsafety.
3568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<TraceItem*> events() const { return events_; }
3668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) private:
3868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  base::Lock lock_;
3968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
4068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<TraceItem*> events_;
4168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
4268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TraceLog);
4368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)};
4468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
4568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)TraceLog* trace_log = NULL;
4668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
4768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)struct Coalesced {
4868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  Coalesced() : name_ptr(NULL), total_duration(0.0), count(0) {}
4968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
5068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const std::string* name_ptr;  // Pointer to a string with the name in it.
5168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  double total_duration;
5268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int count;
5368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)};
5468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
5568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool DurationGreater(const TraceItem* a, const TraceItem* b) {
5668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return a->delta() > b->delta();
5768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
5868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
5968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool CoalescedDurationGreater(const Coalesced& a, const Coalesced& b) {
6068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return a.total_duration > b.total_duration;
6168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
6268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
6368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void SummarizeParses(std::vector<const TraceItem*>& loads,
6468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                     std::ostream& out) {
6568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  out << "File parse times: (time in ms, name)\n";
6668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
6768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::sort(loads.begin(), loads.end(), &DurationGreater);
6868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
6968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (size_t i = 0; i < loads.size(); i++) {
7068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    out << base::StringPrintf(" %8.2f  ",
7168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                              loads[i]->delta().InMillisecondsF());
7268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    out << loads[i]->name() << std::endl;
7368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
7468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
7568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
7668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void SummarizeCoalesced(std::vector<const TraceItem*>& items,
7768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                        std::ostream& out) {
7868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Group by file name.
7968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::map<std::string, Coalesced> coalesced;
8068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (size_t i = 0; i < items.size(); i++) {
8168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    Coalesced& c = coalesced[items[i]->name()];
8268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    c.name_ptr = &items[i]->name();
8368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    c.total_duration += items[i]->delta().InMillisecondsF();
8468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    c.count++;
8568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
8668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
8768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Sort by duration.
8868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<Coalesced> sorted;
8968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (std::map<std::string, Coalesced>::iterator iter = coalesced.begin();
9068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)       iter != coalesced.end(); ++iter)
9168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    sorted.push_back(iter->second);
9268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::sort(sorted.begin(), sorted.end(), &CoalescedDurationGreater);
9368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
9468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (size_t i = 0; i < sorted.size(); i++) {
9568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    out << base::StringPrintf(" %8.2f  %d  ",
9668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                              sorted[i].total_duration, sorted[i].count);
9768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    out << *sorted[i].name_ptr << std::endl;
9868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
9968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
10068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
10168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void SummarizeFileExecs(std::vector<const TraceItem*>& execs,
10268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                        std::ostream& out) {
10368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  out << "File execute times: (total time in ms, # executions, name)\n";
10468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SummarizeCoalesced(execs, out);
10568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
10668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
10768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void SummarizeScriptExecs(std::vector<const TraceItem*>& execs,
10868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                          std::ostream& out) {
10968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  out << "Script execute times: (total time in ms, # executions, name)\n";
11068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SummarizeCoalesced(execs, out);
11168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
11268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
11368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}  // namespace
11468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
11568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)TraceItem::TraceItem(Type type,
11668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                     const std::string& name,
11768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                     base::PlatformThreadId thread_id)
11868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    : type_(type),
11968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      name_(name),
12068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      thread_id_(thread_id) {
12168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
12268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
12368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)TraceItem::~TraceItem() {
12468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
12568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
12668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)ScopedTrace::ScopedTrace(TraceItem::Type t, const std::string& name)
12768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    : item_(NULL),
12868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      done_(false) {
12968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (trace_log) {
13068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    item_ = new TraceItem(t, name, base::PlatformThread::CurrentId());
13168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    item_->set_begin(base::TimeTicks::HighResNow());
13268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
13368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
13468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ScopedTrace::ScopedTrace(TraceItem::Type t, const Label& label)
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : item_(NULL),
137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      done_(false) {
138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (trace_log) {
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    item_ = new TraceItem(t, label.GetUserVisibleName(false),
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                          base::PlatformThread::CurrentId());
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    item_->set_begin(base::TimeTicks::HighResNow());
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
14568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)ScopedTrace::~ScopedTrace() {
14668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  Done();
14768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
14868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
14968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void ScopedTrace::SetToolchain(const Label& label) {
15068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (item_)
15168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    item_->set_toolchain(label.GetUserVisibleName(false));
15268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
15368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
15468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void ScopedTrace::SetCommandLine(const CommandLine& cmdline) {
15568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (item_)
15668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    item_->set_cmdline(FilePathToUTF8(cmdline.GetArgumentsString()));
15768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
15868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
15968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void ScopedTrace::Done() {
16068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!done_) {
16168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    done_ = true;
16268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (trace_log) {
16368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      item_->set_end(base::TimeTicks::HighResNow());
16468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      AddTrace(item_);
16568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
16668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
16768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
16868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
16968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void EnableTracing() {
170010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!trace_log)
171010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    trace_log = new TraceLog;
17268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
17368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
17468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void AddTrace(TraceItem* item) {
17568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  trace_log->Add(item);
17668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
17768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
17868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)std::string SummarizeTraces() {
17968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!trace_log)
18068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return std::string();
18168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
18268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<TraceItem*> events = trace_log->events();
18368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
18468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Classify all events.
18568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<const TraceItem*> parses;
18668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<const TraceItem*> file_execs;
18768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<const TraceItem*> script_execs;
188c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  std::vector<const TraceItem*> check_headers;
189c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int headers_checked = 0;
19068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (size_t i = 0; i < events.size(); i++) {
19168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    switch (events[i]->type()) {
19268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case TraceItem::TRACE_FILE_PARSE:
19368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        parses.push_back(events[i]);
19468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
19568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case TraceItem::TRACE_FILE_EXECUTE:
19668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        file_execs.push_back(events[i]);
19768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
19868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case TraceItem::TRACE_SCRIPT_EXECUTE:
19968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        script_execs.push_back(events[i]);
20068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
201c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      case TraceItem::TRACE_CHECK_HEADERS:
202c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        check_headers.push_back(events[i]);
203c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        break;
204c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      case TraceItem::TRACE_CHECK_HEADER:
205c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        headers_checked++;
206c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        break;
207010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      case TraceItem::TRACE_SETUP:
20868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case TraceItem::TRACE_FILE_LOAD:
20968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case TraceItem::TRACE_FILE_WRITE:
210f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      case TraceItem::TRACE_DEFINE_TARGET:
21168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;  // Ignore these for the summary.
21268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
21368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
21468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
21568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::ostringstream out;
21668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SummarizeParses(parses, out);
21768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  out << std::endl;
21868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SummarizeFileExecs(file_execs, out);
21968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  out << std::endl;
22068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SummarizeScriptExecs(script_execs, out);
22168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  out << std::endl;
22268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
223c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Generally there will only be one header check, but it's theoretically
224c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // possible for more than one to run if more than one build is going in
225c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // parallel. Just report the total of all of them.
226c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!check_headers.empty()) {
227c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    float check_headers_time = 0;
228c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    for (size_t i = 0; i < check_headers.size(); i++)
229c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      check_headers_time += check_headers[i]->delta().InMillisecondsF();
230c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
231c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    out << "Header check time: (total time in ms, files checked)\n";
232c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    out << base::StringPrintf(" %8.2f  %d\n",
233c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                              check_headers_time, headers_checked);
234c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
235c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
23668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return out.str();
23768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
23868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
23968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void SaveTraces(const base::FilePath& file_name) {
24068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::ostringstream out;
24168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
24268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  out << "{\"traceEvents\":[";
24368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
24468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::string quote_buffer;  // Allocate outside loop to prevent reallocationg.
24568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
246f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Write main thread metadata (assume this is being written on the main
247f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // thread).
248f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  out << "{\"pid\":0,\"tid\":" << base::PlatformThread::CurrentId();
249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  out << ",\"ts\":0,\"ph\":\"M\",";
250f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  out << "\"name\":\"thread_name\",\"args\":{\"name\":\"Main thread\"}},";
251f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
25268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<TraceItem*> events = trace_log->events();
25368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (size_t i = 0; i < events.size(); i++) {
25468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const TraceItem& item = *events[i];
25568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
25668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (i != 0)
25768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      out << ",";
25868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    out << "{\"pid\":0,\"tid\":" << item.thread_id();
25968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    out << ",\"ts\":" << item.begin().ToInternalValue();
26068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    out << ",\"ph\":\"X\"";  // "X" = complete event with begin & duration.
26168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    out << ",\"dur\":" << item.delta().InMicroseconds();
26268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
26368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    quote_buffer.resize(0);
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::EscapeJSONString(item.name(), true, &quote_buffer);
26568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    out << ",\"name\":" << quote_buffer;
26668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
26768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    out << ",\"cat\":";
26868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    switch (item.type()) {
269010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      case TraceItem::TRACE_SETUP:
270010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        out << "\"setup\"";
271010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        break;
27268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case TraceItem::TRACE_FILE_LOAD:
27368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        out << "\"load\"";
27468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
27568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case TraceItem::TRACE_FILE_PARSE:
27668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        out << "\"parse\"";
27768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
27868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case TraceItem::TRACE_FILE_EXECUTE:
27968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        out << "\"file_exec\"";
28068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
28168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case TraceItem::TRACE_FILE_WRITE:
28268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        out << "\"file_write\"";
28368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
28468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case TraceItem::TRACE_SCRIPT_EXECUTE:
28568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        out << "\"script_exec\"";
28668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
287f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      case TraceItem::TRACE_DEFINE_TARGET:
288f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        out << "\"define\"";
289c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        break;
290c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      case TraceItem::TRACE_CHECK_HEADER:
291c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        out << "\"hdr\"";
292c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        break;
293c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      case TraceItem::TRACE_CHECK_HEADERS:
294c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        out << "\"header_check\"";
295c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        break;
29668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
29768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
29868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (!item.toolchain().empty() || !item.cmdline().empty()) {
29968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      out << ",\"args\":{";
30068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      bool needs_comma = false;
30168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (!item.toolchain().empty()) {
30268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        quote_buffer.resize(0);
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::EscapeJSONString(item.toolchain(), true, &quote_buffer);
30468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        out << "\"toolchain\":" << quote_buffer;
30568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        needs_comma = true;
30668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
30768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (!item.cmdline().empty()) {
30868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        quote_buffer.resize(0);
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::EscapeJSONString(item.cmdline(), true, &quote_buffer);
31068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        if (needs_comma)
31168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          out << ",";
31268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        out << "\"cmdline\":" << quote_buffer;
31368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        needs_comma = true;
31468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
31568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      out << "}";
31668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
31768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    out << "}";
31868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
31968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
32068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  out << "]}";
32168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
32268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::string out_str = out.str();
323a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::WriteFile(file_name, out_str.data(),
3244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                       static_cast<int>(out_str.size()));
32568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
326