trace.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
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)
1268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/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)  }
2768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ~TraceLog() {
2868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Trace items leanked intentionally.
2968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
3068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  void Add(TraceItem* item) {
3268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    base::AutoLock lock(lock_);
3368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    events_.push_back(item);
3468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
3568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Returns a copy for threadsafety.
3768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<TraceItem*> events() const { return events_; }
3868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) private:
4068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  base::Lock lock_;
4168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
4268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<TraceItem*> events_;
4368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
4468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TraceLog);
4568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)};
4668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
4768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)TraceLog* trace_log = NULL;
4868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
4968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)struct Coalesced {
5068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  Coalesced() : name_ptr(NULL), total_duration(0.0), count(0) {}
5168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
5268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const std::string* name_ptr;  // Pointer to a string with the name in it.
5368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  double total_duration;
5468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int count;
5568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)};
5668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
5768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool DurationGreater(const TraceItem* a, const TraceItem* b) {
5868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return a->delta() > b->delta();
5968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
6068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
6168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool CoalescedDurationGreater(const Coalesced& a, const Coalesced& b) {
6268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return a.total_duration > b.total_duration;
6368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
6468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
6568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void SummarizeParses(std::vector<const TraceItem*>& loads,
6668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                     std::ostream& out) {
6768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  out << "File parse times: (time in ms, name)\n";
6868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
6968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::sort(loads.begin(), loads.end(), &DurationGreater);
7068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
7168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (size_t i = 0; i < loads.size(); i++) {
7268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    out << base::StringPrintf(" %8.2f  ",
7368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                              loads[i]->delta().InMillisecondsF());
7468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    out << loads[i]->name() << std::endl;
7568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
7668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
7768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
7868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void SummarizeCoalesced(std::vector<const TraceItem*>& items,
7968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                        std::ostream& out) {
8068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Group by file name.
8168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::map<std::string, Coalesced> coalesced;
8268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (size_t i = 0; i < items.size(); i++) {
8368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    Coalesced& c = coalesced[items[i]->name()];
8468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    c.name_ptr = &items[i]->name();
8568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    c.total_duration += items[i]->delta().InMillisecondsF();
8668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    c.count++;
8768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
8868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
8968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Sort by duration.
9068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<Coalesced> sorted;
9168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (std::map<std::string, Coalesced>::iterator iter = coalesced.begin();
9268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)       iter != coalesced.end(); ++iter)
9368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    sorted.push_back(iter->second);
9468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::sort(sorted.begin(), sorted.end(), &CoalescedDurationGreater);
9568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
9668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (size_t i = 0; i < sorted.size(); i++) {
9768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    out << base::StringPrintf(" %8.2f  %d  ",
9868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                              sorted[i].total_duration, sorted[i].count);
9968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    out << *sorted[i].name_ptr << std::endl;
10068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
10168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
10268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
10368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void SummarizeFileExecs(std::vector<const TraceItem*>& execs,
10468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                        std::ostream& out) {
10568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  out << "File execute times: (total time in ms, # executions, name)\n";
10668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SummarizeCoalesced(execs, out);
10768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
10868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
10968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void SummarizeScriptExecs(std::vector<const TraceItem*>& execs,
11068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                          std::ostream& out) {
11168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  out << "Script execute times: (total time in ms, # executions, name)\n";
11268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SummarizeCoalesced(execs, out);
11368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
11468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
11568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}  // namespace
11668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
11768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)TraceItem::TraceItem(Type type,
11868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                     const std::string& name,
11968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                     base::PlatformThreadId thread_id)
12068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    : type_(type),
12168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      name_(name),
12268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      thread_id_(thread_id) {
12368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
12468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
12568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)TraceItem::~TraceItem() {
12668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
12768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
12868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)ScopedTrace::ScopedTrace(TraceItem::Type t, const std::string& name)
12968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    : item_(NULL),
13068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      done_(false) {
13168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (trace_log) {
13268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    item_ = new TraceItem(t, name, base::PlatformThread::CurrentId());
13368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    item_->set_begin(base::TimeTicks::HighResNow());
13468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
13568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
13668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
13768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)ScopedTrace::~ScopedTrace() {
13868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  Done();
13968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
14068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
14168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void ScopedTrace::SetToolchain(const Label& label) {
14268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (item_)
14368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    item_->set_toolchain(label.GetUserVisibleName(false));
14468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
14568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
14668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void ScopedTrace::SetCommandLine(const CommandLine& cmdline) {
14768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (item_)
14868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    item_->set_cmdline(FilePathToUTF8(cmdline.GetArgumentsString()));
14968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
15068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
15168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void ScopedTrace::Done() {
15268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!done_) {
15368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    done_ = true;
15468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (trace_log) {
15568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      item_->set_end(base::TimeTicks::HighResNow());
15668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      AddTrace(item_);
15768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
15868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
15968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
16068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
16168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void EnableTracing() {
16268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  CHECK(!trace_log);
16368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  trace_log = new TraceLog;
16468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
16568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
16668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void AddTrace(TraceItem* item) {
16768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  trace_log->Add(item);
16868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
16968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
17068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)std::string SummarizeTraces() {
17168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!trace_log)
17268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return std::string();
17368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
17468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<TraceItem*> events = trace_log->events();
17568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
17668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Classify all events.
17768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<const TraceItem*> parses;
17868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<const TraceItem*> file_execs;
17968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<const TraceItem*> script_execs;
18068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (size_t i = 0; i < events.size(); i++) {
18168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    switch (events[i]->type()) {
18268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case TraceItem::TRACE_FILE_PARSE:
18368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        parses.push_back(events[i]);
18468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
18568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case TraceItem::TRACE_FILE_EXECUTE:
18668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        file_execs.push_back(events[i]);
18768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
18868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case TraceItem::TRACE_SCRIPT_EXECUTE:
18968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        script_execs.push_back(events[i]);
19068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
19168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case TraceItem::TRACE_FILE_LOAD:
19268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case TraceItem::TRACE_FILE_WRITE:
19368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;  // Ignore these for the summary.
19468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
19568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
19668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
19768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::ostringstream out;
19868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SummarizeParses(parses, out);
19968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  out << std::endl;
20068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SummarizeFileExecs(file_execs, out);
20168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  out << std::endl;
20268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SummarizeScriptExecs(script_execs, out);
20368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  out << std::endl;
20468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
20568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return out.str();
20668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
20768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
20868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void SaveTraces(const base::FilePath& file_name) {
20968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::ostringstream out;
21068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
21168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  out << "{\"traceEvents\":[";
21268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
21368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::string quote_buffer;  // Allocate outside loop to prevent reallocationg.
21468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
21568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<TraceItem*> events = trace_log->events();
21668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (size_t i = 0; i < events.size(); i++) {
21768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const TraceItem& item = *events[i];
21868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
21968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (i != 0)
22068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      out << ",";
22168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    out << "{\"pid\":0,\"tid\":" << item.thread_id();
22268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    out << ",\"ts\":" << item.begin().ToInternalValue();
22368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    out << ",\"ph\":\"X\"";  // "X" = complete event with begin & duration.
22468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    out << ",\"dur\":" << item.delta().InMicroseconds();
22568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
22668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    quote_buffer.resize(0);
22768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    base::JsonDoubleQuote(item.name(), true, &quote_buffer);
22868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    out << ",\"name\":" << quote_buffer;
22968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
23068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    out << ",\"cat\":";
23168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    switch (item.type()) {
23268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case TraceItem::TRACE_FILE_LOAD:
23368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        out << "\"load\"";
23468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
23568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case TraceItem::TRACE_FILE_PARSE:
23668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        out << "\"parse\"";
23768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
23868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case TraceItem::TRACE_FILE_EXECUTE:
23968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        out << "\"file_exec\"";
24068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
24168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case TraceItem::TRACE_FILE_WRITE:
24268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        out << "\"file_write\"";
24368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
24468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case TraceItem::TRACE_SCRIPT_EXECUTE:
24568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        out << "\"script_exec\"";
24668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
24768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
24868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
24968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (!item.toolchain().empty() || !item.cmdline().empty()) {
25068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      out << ",\"args\":{";
25168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      bool needs_comma = false;
25268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (!item.toolchain().empty()) {
25368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        quote_buffer.resize(0);
25468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        base::JsonDoubleQuote(item.toolchain(), true, &quote_buffer);
25568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        out << "\"toolchain\":" << quote_buffer;
25668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        needs_comma = true;
25768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
25868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (!item.cmdline().empty()) {
25968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        quote_buffer.resize(0);
26068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        base::JsonDoubleQuote(item.cmdline(), true, &quote_buffer);
26168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        if (needs_comma)
26268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          out << ",";
26368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        out << "\"cmdline\":" << quote_buffer;
26468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        needs_comma = true;
26568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
26668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      out << "}";
26768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
26868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    out << "}";
26968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
27068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
27168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  out << "]}";
27268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
27368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::string out_str = out.str();
27468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  file_util::WriteFile(file_name, out_str.data(), out_str.size());
27568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
276