Skip to content
This repository
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 145 lines (122 sloc) 3.923 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
// Copyright 2012 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <stdio.h>
#include <stdlib.h>

#include "build_log.h"
#include "graph.h"
#include "manifest_parser.h"
#include "state.h"
#include "util.h"
#include "metrics.h"

#ifndef _WIN32
#include <unistd.h>
#endif

const char kTestFilename[] = "BuildLogPerfTest-tempfile";

bool WriteTestData(string* err) {
  BuildLog log;

  if (!log.OpenForWrite(kTestFilename, err))
    return false;

  /*
A histogram of command lengths in chromium. For example, 407 builds,
1.4% of all builds, had commands longer than 32 bytes but shorter than 64.
32 407 1.4%
64 183 0.6%
128 1461 5.1%
256 791 2.8%
512 1314 4.6%
1024 6114 21.3%
2048 11759 41.0%
4096 2056 7.2%
8192 4567 15.9%
16384 13 0.0%
32768 4 0.0%
65536 5 0.0%
The average command length is 4.1 kB and there were 28674 commands in total,
which makes for a total log size of ~120 MB (also counting output filenames).

Based on this, write 30000 many 4 kB long command lines.
*/

  // ManifestParser is the only object allowed to create Rules.
  const size_t kRuleSize = 4000;
  string long_rule_command = "gcc ";
  for (int i = 0; long_rule_command.size() < kRuleSize; ++i) {
    char buf[80];
    sprintf(buf, "-I../../and/arbitrary/but/fairly/long/path/suffixed/%d ", i);
    long_rule_command += buf;
  }
  long_rule_command += "$in -o $out\n";

  State state;
  ManifestParser parser(&state, NULL);
  if (!parser.ParseTest("rule cxx\n command = " + long_rule_command, err))
    return false;

  // Create build edges. Using ManifestParser is as fast as using the State api
  // for edge creation, so just use that.
  const int kNumCommands = 30000;
  string build_rules;
  for (int i = 0; i < kNumCommands; ++i) {
    char buf[80];
    sprintf(buf, "build input%d.o: cxx input%d.cc\n", i, i);
    build_rules += buf;
  }

  if (!parser.ParseTest(build_rules, err))
    return false;

  for (int i = 0; i < kNumCommands; ++i) {
    log.RecordCommand(state.edges_[i],
                      /*start_time=*/100 * i,
                      /*end_time=*/100 * i + 1,
                      /*restat_mtime=*/0);
  }

  return true;
}

int main() {
  vector<int> times;
  string err;

  if (!WriteTestData(&err)) {
    fprintf(stderr, "Failed to write test data: %s\n", err.c_str());
    return 1;
  }

  {
    // Read once to warm up disk cache.
    BuildLog log;
    if (!log.Load(kTestFilename, &err)) {
      fprintf(stderr, "Failed to read test data: %s\n", err.c_str());
      return 1;
    }
  }
  const int kNumRepetitions = 5;
  for (int i = 0; i < kNumRepetitions; ++i) {
    int64_t start = GetTimeMillis();
    BuildLog log;
    if (!log.Load(kTestFilename, &err)) {
      fprintf(stderr, "Failed to read test data: %s\n", err.c_str());
      return 1;
    }
    int delta = (int)(GetTimeMillis() - start);
    printf("%dms\n", delta);
    times.push_back(delta);
  }

  int min = times[0];
  int max = times[0];
  float total = 0;
  for (size_t i = 0; i < times.size(); ++i) {
    total += times[i];
    if (times[i] < min)
      min = times[i];
    else if (times[i] > max)
      max = times[i];
  }

  printf("min %dms max %dms avg %.1fms\n",
         min, max, total / times.size());

  unlink(kTestFilename);

  return 0;
}

Something went wrong with that request. Please try again.