1 // Copyright 2012 Google Inc. All Rights Reserved.
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include "build_log.h"
20 #include "manifest_parser.h"
29 const char kTestFilename[] = "BuildLogPerfTest-tempfile";
31 struct NoDeadPaths : public BuildLogUser {
32 virtual bool IsPathDead(StringPiece) const { return false; }
35 bool WriteTestData(string* err) {
38 NoDeadPaths no_dead_paths;
39 if (!log.OpenForWrite(kTestFilename, no_dead_paths, err))
43 A histogram of command lengths in chromium. For example, 407 builds,
44 1.4% of all builds, had commands longer than 32 bytes but shorter than 64.
57 The average command length is 4.1 kB and there were 28674 commands in total,
58 which makes for a total log size of ~120 MB (also counting output filenames).
60 Based on this, write 30000 many 4 kB long command lines.
63 // ManifestParser is the only object allowed to create Rules.
64 const size_t kRuleSize = 4000;
65 string long_rule_command = "gcc ";
66 for (int i = 0; long_rule_command.size() < kRuleSize; ++i) {
68 sprintf(buf, "-I../../and/arbitrary/but/fairly/long/path/suffixed/%d ", i);
69 long_rule_command += buf;
71 long_rule_command += "$in -o $out\n";
74 ManifestParser parser(&state, NULL, kDupeEdgeActionWarn);
75 if (!parser.ParseTest("rule cxx\n command = " + long_rule_command, err))
78 // Create build edges. Using ManifestParser is as fast as using the State api
79 // for edge creation, so just use that.
80 const int kNumCommands = 30000;
82 for (int i = 0; i < kNumCommands; ++i) {
84 sprintf(buf, "build input%d.o: cxx input%d.cc\n", i, i);
88 if (!parser.ParseTest(build_rules, err))
91 for (int i = 0; i < kNumCommands; ++i) {
92 log.RecordCommand(state.edges_[i],
93 /*start_time=*/100 * i,
94 /*end_time=*/100 * i + 1,
105 if (!WriteTestData(&err)) {
106 fprintf(stderr, "Failed to write test data: %s\n", err.c_str());
111 // Read once to warm up disk cache.
113 if (!log.Load(kTestFilename, &err)) {
114 fprintf(stderr, "Failed to read test data: %s\n", err.c_str());
118 const int kNumRepetitions = 5;
119 for (int i = 0; i < kNumRepetitions; ++i) {
120 int64_t start = GetTimeMillis();
122 if (!log.Load(kTestFilename, &err)) {
123 fprintf(stderr, "Failed to read test data: %s\n", err.c_str());
126 int delta = (int)(GetTimeMillis() - start);
127 printf("%dms\n", delta);
128 times.push_back(delta);
134 for (size_t i = 0; i < times.size(); ++i) {
138 else if (times[i] > max)
142 printf("min %dms max %dms avg %.1fms\n",
143 min, max, total / times.size());
145 unlink(kTestFilename);