main.cpp revision 8160f20b0aca8c6595d4b385d673f59b6bcd16a4
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "Benchmark.h"
18
19#include "protos/hwui.pb.h"
20
21#include <getopt.h>
22#include <stdio.h>
23#include <string>
24#include <unistd.h>
25#include <unordered_map>
26#include <vector>
27
28using namespace android;
29using namespace android::uirenderer;
30
31// Not a static global because we need to force the map to be constructed
32// before we try to add things to it.
33std::unordered_map<std::string, BenchmarkInfo>& testMap() {
34    static std::unordered_map<std::string, BenchmarkInfo> testMap;
35    return testMap;
36}
37
38void Benchmark::registerBenchmark(const BenchmarkInfo& info) {
39    testMap()[info.name] = info;
40}
41
42static int gFrameCount = 150;
43static int gRepeatCount = 1;
44static std::vector<BenchmarkInfo> gRunTests;
45
46void run(const BenchmarkInfo& info, const BenchmarkOptions& opts);
47
48static void printHelp() {
49    printf("\
50USAGE: hwuitest [OPTIONS] <TESTNAME>\n\
51\n\
52OPTIONS:\n\
53  -c, --count=NUM      NUM loops a test should run (example, number of frames)\n\
54  -r, --runs=NUM       Repeat the test(s) NUM times\n\
55  -h, --help           Display this help\n\
56  --list               List all tests\n\
57\n");
58}
59
60static void listTests() {
61    printf("Tests: \n");
62    for (auto&& test : testMap()) {
63        auto&& info = test.second;
64        const char* col1 = info.name.c_str();
65        int dlen = info.description.length();
66        const char* col2 = info.description.c_str();
67        // World's best line breaking algorithm.
68        do {
69            int toPrint = dlen;
70            if (toPrint > 50) {
71                char* found = (char*) memrchr(col2, ' ', 50);
72                if (found) {
73                    toPrint = found - col2;
74                } else {
75                    toPrint = 50;
76                }
77            }
78            printf("%-20s %.*s\n", col1, toPrint, col2);
79            col1 = "";
80            col2 += toPrint;
81            dlen -= toPrint;
82            while (*col2 == ' ') {
83                col2++; dlen--;
84            }
85        } while (dlen > 0);
86        printf("\n");
87    }
88}
89
90static const struct option LONG_OPTIONS[] = {
91    { "frames", required_argument, nullptr, 'f' },
92    { "repeat", required_argument, nullptr, 'r' },
93    { "help", no_argument, nullptr, 'h' },
94    { "list", no_argument, nullptr, 'l' },
95    { 0, 0, 0, 0 }
96};
97
98static const char* SHORT_OPTIONS = "c:r:h";
99
100void parseOptions(int argc, char* argv[]) {
101    int c;
102    // temporary variable
103    int count;
104    bool error = false;
105    opterr = 0;
106
107    while (true) {
108
109        /* getopt_long stores the option index here. */
110        int option_index = 0;
111
112        c = getopt_long(argc, argv, SHORT_OPTIONS, LONG_OPTIONS, &option_index);
113
114        if (c == -1)
115            break;
116
117        switch (c) {
118        case 0:
119            // Option set a flag, don't need to do anything
120            // (although none of the current LONG_OPTIONS do this...)
121            break;
122
123        case 'l':
124            listTests();
125            exit(EXIT_SUCCESS);
126            break;
127
128        case 'c':
129            count = atoi(optarg);
130            if (!count) {
131                fprintf(stderr, "Invalid frames argument '%s'\n", optarg);
132                error = true;
133            } else {
134                gFrameCount = (count > 0 ? count : INT_MAX);
135            }
136            break;
137
138        case 'r':
139            count = atoi(optarg);
140            if (!count) {
141                fprintf(stderr, "Invalid repeat argument '%s'\n", optarg);
142                error = true;
143            } else {
144                gRepeatCount = (count > 0 ? count : INT_MAX);
145            }
146            break;
147
148        case 'h':
149            printHelp();
150            exit(EXIT_SUCCESS);
151            break;
152
153        case '?':
154            fprintf(stderr, "Unrecognized option '%s'\n", argv[optind - 1]);
155            // fall-through
156        default:
157            error = true;
158            break;
159        }
160    }
161
162    if (error) {
163        fprintf(stderr, "Try 'hwuitest --help' for more information.\n");
164        exit(EXIT_FAILURE);
165    }
166
167    /* Print any remaining command line arguments (not options). */
168    if (optind < argc) {
169        do {
170            const char* test = argv[optind++];
171            auto pos = testMap().find(test);
172            if (pos == testMap().end()) {
173                fprintf(stderr, "Unknown test '%s'\n", test);
174                exit(EXIT_FAILURE);
175            } else {
176                gRunTests.push_back(pos->second);
177            }
178        } while (optind < argc);
179    } else {
180        gRunTests.push_back(testMap()["shadowgrid"]);
181    }
182}
183
184int main(int argc, char* argv[]) {
185    parseOptions(argc, argv);
186
187    BenchmarkOptions opts;
188    opts.count = gFrameCount;
189    for (int i = 0; i < gRepeatCount; i++) {
190        for (auto&& test : gRunTests) {
191            run(test, opts);
192        }
193    }
194    printf("Success!\n");
195    return 0;
196}
197