Ninja
build_log_perftest.cc
Go to the documentation of this file.
1 // Copyright 2012 Google Inc. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <stdio.h>
16 #include <stdlib.h>
17 
18 #include "build_log.h"
19 #include "graph.h"
20 #include "manifest_parser.h"
21 #include "state.h"
22 #include "util.h"
23 #include "metrics.h"
24 
25 #ifndef _WIN32
26 #include <unistd.h>
27 #endif
28 
29 const char kTestFilename[] = "BuildLogPerfTest-tempfile";
30 
31 bool WriteTestData(string* err) {
32  BuildLog log;
33 
34  if (!log.OpenForWrite(kTestFilename, err))
35  return false;
36 
37  /*
38  A histogram of command lengths in chromium. For example, 407 builds,
39  1.4% of all builds, had commands longer than 32 bytes but shorter than 64.
40  32 407 1.4%
41  64 183 0.6%
42  128 1461 5.1%
43  256 791 2.8%
44  512 1314 4.6%
45  1024 6114 21.3%
46  2048 11759 41.0%
47  4096 2056 7.2%
48  8192 4567 15.9%
49  16384 13 0.0%
50  32768 4 0.0%
51  65536 5 0.0%
52  The average command length is 4.1 kB and there were 28674 commands in total,
53  which makes for a total log size of ~120 MB (also counting output filenames).
54 
55  Based on this, write 30000 many 4 kB long command lines.
56  */
57 
58  // ManifestParser is the only object allowed to create Rules.
59  const size_t kRuleSize = 4000;
60  string long_rule_command = "gcc ";
61  for (int i = 0; long_rule_command.size() < kRuleSize; ++i) {
62  char buf[80];
63  sprintf(buf, "-I../../and/arbitrary/but/fairly/long/path/suffixed/%d ", i);
64  long_rule_command += buf;
65  }
66  long_rule_command += "$in -o $out\n";
67 
68  State state;
69  ManifestParser parser(&state, NULL);
70  if (!parser.ParseTest("rule cxx\n command = " + long_rule_command, err))
71  return false;
72 
73  // Create build edges. Using ManifestParser is as fast as using the State api
74  // for edge creation, so just use that.
75  const int kNumCommands = 30000;
76  string build_rules;
77  for (int i = 0; i < kNumCommands; ++i) {
78  char buf[80];
79  sprintf(buf, "build input%d.o: cxx input%d.cc\n", i, i);
80  build_rules += buf;
81  }
82 
83  if (!parser.ParseTest(build_rules, err))
84  return false;
85 
86  for (int i = 0; i < kNumCommands; ++i) {
87  log.RecordCommand(state.edges_[i],
88  /*start_time=*/100 * i,
89  /*end_time=*/100 * i + 1,
90  /*restat_mtime=*/0);
91  }
92 
93  return true;
94 }
95 
96 int main() {
97  vector<int> times;
98  string err;
99 
100  if (!WriteTestData(&err)) {
101  fprintf(stderr, "Failed to write test data: %s\n", err.c_str());
102  return 1;
103  }
104 
105  {
106  // Read once to warm up disk cache.
107  BuildLog log;
108  if (!log.Load(kTestFilename, &err)) {
109  fprintf(stderr, "Failed to read test data: %s\n", err.c_str());
110  return 1;
111  }
112  }
113  const int kNumRepetitions = 5;
114  for (int i = 0; i < kNumRepetitions; ++i) {
115  int64_t start = GetTimeMillis();
116  BuildLog log;
117  if (!log.Load(kTestFilename, &err)) {
118  fprintf(stderr, "Failed to read test data: %s\n", err.c_str());
119  return 1;
120  }
121  int delta = (int)(GetTimeMillis() - start);
122  printf("%dms\n", delta);
123  times.push_back(delta);
124  }
125 
126  int min = times[0];
127  int max = times[0];
128  float total = 0;
129  for (size_t i = 0; i < times.size(); ++i) {
130  total += times[i];
131  if (times[i] < min)
132  min = times[i];
133  else if (times[i] > max)
134  max = times[i];
135  }
136 
137  printf("min %dms max %dms avg %.1fms\n",
138  min, max, total / times.size());
139 
140  unlink(kTestFilename);
141 
142  return 0;
143 }
144 
bool OpenForWrite(const string &path, string *err)
Definition: build_log.cc:110
vector< Edge * > edges_
All the edges of the graph.
Definition: state.h:128
int main()
int64_t GetTimeMillis()
Get the current time as relative to some epoch.
Definition: metrics.cc:122
Store a log of every command ran for every build.
Definition: build_log.h:35
void RecordCommand(Edge *edge, int start_time, int end_time, TimeStamp restat_mtime=0)
Definition: build_log.cc:139
signed long long int64_t
A 64-bit integer type.
Definition: win32port.h:21
Parses .ninja files.
bool WriteTestData(string *err)
const char kTestFilename[]
Global state (file status, loaded rules) for a single run.
Definition: state.h:83
bool Load(const string &path, string *err)
Load the on-disk log.
Definition: build_log.cc:221
bool ParseTest(const string &input, string *err)
Parse a text string of input. Used by tests.