Ninja
|
00001 // Copyright 2012 Google Inc. All Rights Reserved. 00002 // 00003 // Licensed under the Apache License, Version 2.0 (the "License"); 00004 // you may not use this file except in compliance with the License. 00005 // You may obtain a copy of the License at 00006 // 00007 // http://www.apache.org/licenses/LICENSE-2.0 00008 // 00009 // Unless required by applicable law or agreed to in writing, software 00010 // distributed under the License is distributed on an "AS IS" BASIS, 00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 // See the License for the specific language governing permissions and 00013 // limitations under the License. 00014 00015 #include <stdio.h> 00016 #include <stdlib.h> 00017 00018 #include "build_log.h" 00019 #include "graph.h" 00020 #include "manifest_parser.h" 00021 #include "state.h" 00022 #include "util.h" 00023 #include "metrics.h" 00024 00025 #ifndef _WIN32 00026 #include <unistd.h> 00027 #endif 00028 00029 const char kTestFilename[] = "BuildLogPerfTest-tempfile"; 00030 00031 bool WriteTestData(string* err) { 00032 BuildLog log; 00033 00034 if (!log.OpenForWrite(kTestFilename, err)) 00035 return false; 00036 00037 /* 00038 A histogram of command lengths in chromium. For example, 407 builds, 00039 1.4% of all builds, had commands longer than 32 bytes but shorter than 64. 00040 32 407 1.4% 00041 64 183 0.6% 00042 128 1461 5.1% 00043 256 791 2.8% 00044 512 1314 4.6% 00045 1024 6114 21.3% 00046 2048 11759 41.0% 00047 4096 2056 7.2% 00048 8192 4567 15.9% 00049 16384 13 0.0% 00050 32768 4 0.0% 00051 65536 5 0.0% 00052 The average command length is 4.1 kB and there were 28674 commands in total, 00053 which makes for a total log size of ~120 MB (also counting output filenames). 00054 00055 Based on this, write 30000 many 4 kB long command lines. 00056 */ 00057 00058 // ManifestParser is the only object allowed to create Rules. 00059 const size_t kRuleSize = 4000; 00060 string long_rule_command = "gcc "; 00061 for (int i = 0; long_rule_command.size() < kRuleSize; ++i) { 00062 char buf[80]; 00063 sprintf(buf, "-I../../and/arbitrary/but/fairly/long/path/suffixed/%d ", i); 00064 long_rule_command += buf; 00065 } 00066 long_rule_command += "$in -o $out\n"; 00067 00068 State state; 00069 ManifestParser parser(&state, NULL); 00070 if (!parser.ParseTest("rule cxx\n command = " + long_rule_command, err)) 00071 return false; 00072 00073 // Create build edges. Using ManifestParser is as fast as using the State api 00074 // for edge creation, so just use that. 00075 const int kNumCommands = 30000; 00076 string build_rules; 00077 for (int i = 0; i < kNumCommands; ++i) { 00078 char buf[80]; 00079 sprintf(buf, "build input%d.o: cxx input%d.cc\n", i, i); 00080 build_rules += buf; 00081 } 00082 00083 if (!parser.ParseTest(build_rules, err)) 00084 return false; 00085 00086 for (int i = 0; i < kNumCommands; ++i) { 00087 log.RecordCommand(state.edges_[i], 00088 /*start_time=*/100 * i, 00089 /*end_time=*/100 * i + 1, 00090 /*restat_mtime=*/0); 00091 } 00092 00093 return true; 00094 } 00095 00096 int main() { 00097 vector<int> times; 00098 string err; 00099 00100 if (!WriteTestData(&err)) { 00101 fprintf(stderr, "Failed to write test data: %s\n", err.c_str()); 00102 return 1; 00103 } 00104 00105 { 00106 // Read once to warm up disk cache. 00107 BuildLog log; 00108 if (!log.Load(kTestFilename, &err)) { 00109 fprintf(stderr, "Failed to read test data: %s\n", err.c_str()); 00110 return 1; 00111 } 00112 } 00113 const int kNumRepetitions = 5; 00114 for (int i = 0; i < kNumRepetitions; ++i) { 00115 int64_t start = GetTimeMillis(); 00116 BuildLog log; 00117 if (!log.Load(kTestFilename, &err)) { 00118 fprintf(stderr, "Failed to read test data: %s\n", err.c_str()); 00119 return 1; 00120 } 00121 int delta = (int)(GetTimeMillis() - start); 00122 printf("%dms\n", delta); 00123 times.push_back(delta); 00124 } 00125 00126 int min = times[0]; 00127 int max = times[0]; 00128 float total = 0; 00129 for (size_t i = 0; i < times.size(); ++i) { 00130 total += times[i]; 00131 if (times[i] < min) 00132 min = times[i]; 00133 else if (times[i] > max) 00134 max = times[i]; 00135 } 00136 00137 printf("min %dms max %dms avg %.1fms\n", 00138 min, max, total / times.size()); 00139 00140 unlink(kTestFilename); 00141 00142 return 0; 00143 } 00144