1695b41eeSopenharmony_ci// Copyright 2014 Google Inc. All Rights Reserved. 2695b41eeSopenharmony_ci// 3695b41eeSopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 4695b41eeSopenharmony_ci// you may not use this file except in compliance with the License. 5695b41eeSopenharmony_ci// You may obtain a copy of the License at 6695b41eeSopenharmony_ci// 7695b41eeSopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 8695b41eeSopenharmony_ci// 9695b41eeSopenharmony_ci// Unless required by applicable law or agreed to in writing, software 10695b41eeSopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 11695b41eeSopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12695b41eeSopenharmony_ci// See the License for the specific language governing permissions and 13695b41eeSopenharmony_ci// limitations under the License. 14695b41eeSopenharmony_ci 15695b41eeSopenharmony_ci// Tests manifest parser performance. Expects to be run in ninja's root 16695b41eeSopenharmony_ci// directory. 17695b41eeSopenharmony_ci 18695b41eeSopenharmony_ci#include <numeric> 19695b41eeSopenharmony_ci 20695b41eeSopenharmony_ci#include <errno.h> 21695b41eeSopenharmony_ci#include <stdio.h> 22695b41eeSopenharmony_ci#include <stdlib.h> 23695b41eeSopenharmony_ci#include <string.h> 24695b41eeSopenharmony_ci 25695b41eeSopenharmony_ci#ifdef _WIN32 26695b41eeSopenharmony_ci#include "getopt.h" 27695b41eeSopenharmony_ci#include <direct.h> 28695b41eeSopenharmony_ci#elif defined(_AIX) 29695b41eeSopenharmony_ci#include "getopt.h" 30695b41eeSopenharmony_ci#include <unistd.h> 31695b41eeSopenharmony_ci#else 32695b41eeSopenharmony_ci#include <getopt.h> 33695b41eeSopenharmony_ci#include <unistd.h> 34695b41eeSopenharmony_ci#endif 35695b41eeSopenharmony_ci 36695b41eeSopenharmony_ci#include "disk_interface.h" 37695b41eeSopenharmony_ci#include "graph.h" 38695b41eeSopenharmony_ci#include "manifest_parser.h" 39695b41eeSopenharmony_ci#include "metrics.h" 40695b41eeSopenharmony_ci#include "state.h" 41695b41eeSopenharmony_ci#include "util.h" 42695b41eeSopenharmony_ci 43695b41eeSopenharmony_ciusing namespace std; 44695b41eeSopenharmony_ci 45695b41eeSopenharmony_cibool WriteFakeManifests(const string& dir, string* err) { 46695b41eeSopenharmony_ci RealDiskInterface disk_interface; 47695b41eeSopenharmony_ci TimeStamp mtime = disk_interface.Stat(dir + "/build.ninja", err); 48695b41eeSopenharmony_ci if (mtime != 0) // 0 means that the file doesn't exist yet. 49695b41eeSopenharmony_ci return mtime != -1; 50695b41eeSopenharmony_ci 51695b41eeSopenharmony_ci string command = "python misc/write_fake_manifests.py " + dir; 52695b41eeSopenharmony_ci printf("Creating manifest data..."); fflush(stdout); 53695b41eeSopenharmony_ci int exit_code = system(command.c_str()); 54695b41eeSopenharmony_ci printf("done.\n"); 55695b41eeSopenharmony_ci if (exit_code != 0) 56695b41eeSopenharmony_ci *err = "Failed to run " + command; 57695b41eeSopenharmony_ci return exit_code == 0; 58695b41eeSopenharmony_ci} 59695b41eeSopenharmony_ci 60695b41eeSopenharmony_ciint LoadManifests(bool measure_command_evaluation) { 61695b41eeSopenharmony_ci string err; 62695b41eeSopenharmony_ci RealDiskInterface disk_interface; 63695b41eeSopenharmony_ci State state; 64695b41eeSopenharmony_ci ManifestParser parser(&state, &disk_interface); 65695b41eeSopenharmony_ci if (!parser.Load("build.ninja", &err)) { 66695b41eeSopenharmony_ci fprintf(stderr, "Failed to read test data: %s\n", err.c_str()); 67695b41eeSopenharmony_ci exit(1); 68695b41eeSopenharmony_ci } 69695b41eeSopenharmony_ci // Doing an empty build involves reading the manifest and evaluating all 70695b41eeSopenharmony_ci // commands required for the requested targets. So include command 71695b41eeSopenharmony_ci // evaluation in the perftest by default. 72695b41eeSopenharmony_ci int optimization_guard = 0; 73695b41eeSopenharmony_ci if (measure_command_evaluation) 74695b41eeSopenharmony_ci for (size_t i = 0; i < state.edges_.size(); ++i) 75695b41eeSopenharmony_ci optimization_guard += state.edges_[i]->EvaluateCommand().size(); 76695b41eeSopenharmony_ci return optimization_guard; 77695b41eeSopenharmony_ci} 78695b41eeSopenharmony_ci 79695b41eeSopenharmony_ciint main(int argc, char* argv[]) { 80695b41eeSopenharmony_ci bool measure_command_evaluation = true; 81695b41eeSopenharmony_ci int opt; 82695b41eeSopenharmony_ci while ((opt = getopt(argc, argv, const_cast<char*>("fh"))) != -1) { 83695b41eeSopenharmony_ci switch (opt) { 84695b41eeSopenharmony_ci case 'f': 85695b41eeSopenharmony_ci measure_command_evaluation = false; 86695b41eeSopenharmony_ci break; 87695b41eeSopenharmony_ci case 'h': 88695b41eeSopenharmony_ci default: 89695b41eeSopenharmony_ci printf("usage: manifest_parser_perftest\n" 90695b41eeSopenharmony_ci"\n" 91695b41eeSopenharmony_ci"options:\n" 92695b41eeSopenharmony_ci" -f only measure manifest load time, not command evaluation time\n" 93695b41eeSopenharmony_ci ); 94695b41eeSopenharmony_ci return 1; 95695b41eeSopenharmony_ci } 96695b41eeSopenharmony_ci } 97695b41eeSopenharmony_ci 98695b41eeSopenharmony_ci const char kManifestDir[] = "build/manifest_perftest"; 99695b41eeSopenharmony_ci 100695b41eeSopenharmony_ci string err; 101695b41eeSopenharmony_ci if (!WriteFakeManifests(kManifestDir, &err)) { 102695b41eeSopenharmony_ci fprintf(stderr, "Failed to write test data: %s\n", err.c_str()); 103695b41eeSopenharmony_ci return 1; 104695b41eeSopenharmony_ci } 105695b41eeSopenharmony_ci 106695b41eeSopenharmony_ci if (chdir(kManifestDir) < 0) 107695b41eeSopenharmony_ci Fatal("chdir: %s", strerror(errno)); 108695b41eeSopenharmony_ci 109695b41eeSopenharmony_ci const int kNumRepetitions = 5; 110695b41eeSopenharmony_ci vector<int> times; 111695b41eeSopenharmony_ci for (int i = 0; i < kNumRepetitions; ++i) { 112695b41eeSopenharmony_ci int64_t start = GetTimeMillis(); 113695b41eeSopenharmony_ci int optimization_guard = LoadManifests(measure_command_evaluation); 114695b41eeSopenharmony_ci int delta = (int)(GetTimeMillis() - start); 115695b41eeSopenharmony_ci printf("%dms (hash: %x)\n", delta, optimization_guard); 116695b41eeSopenharmony_ci times.push_back(delta); 117695b41eeSopenharmony_ci } 118695b41eeSopenharmony_ci 119695b41eeSopenharmony_ci int min = *min_element(times.begin(), times.end()); 120695b41eeSopenharmony_ci int max = *max_element(times.begin(), times.end()); 121695b41eeSopenharmony_ci float total = accumulate(times.begin(), times.end(), 0.0f); 122695b41eeSopenharmony_ci printf("min %dms max %dms avg %.1fms\n", min, max, total / times.size()); 123695b41eeSopenharmony_ci} 124