This commit is contained in:
2024-09-27 19:16:49 +08:00
commit 49d0cea04d
10000 changed files with 1616312 additions and 0 deletions

View File

@@ -0,0 +1,284 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* 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 <benchmark/benchmark.h>
#include <err.h>
#include <getopt.h>
#include <cinttypes>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include "benchmark_fwk.h"
using namespace std;
using namespace init_benchmark_test;
namespace {
constexpr auto K = 1024;
using args_vector = std::vector<std::vector<int64_t>>;
static const std::vector<int> commonArgs {
8,
16,
32,
64,
512,
1 * K,
8 * K,
16 * K,
32 * K,
64 * K,
128 * K,
};
static const std::vector<int> limitSizes {
1,
2,
3,
4,
5,
6,
7,
};
}
namespace init_benchmark_test {
std::map<std::string, std::pair<benchmark_func, std::string>> g_allBenchmarks;
std::mutex g_benchmarkLock;
static struct option g_benchmarkLongOptions[] = {
{"init_cpu", required_argument, nullptr, 'c'},
{"init_iterations", required_argument, nullptr, 'i'},
{"help", no_argument, nullptr, 'h'},
{nullptr, 0, nullptr, 0},
};
}
static void PrintUsageAndExit()
{
printf("Usage:\n");
printf("init_benchmarks [--init_cpu=<cpu_to_isolate>]\n");
printf(" [--init_iterations=<num_iter>]\n");
printf(" [<original benchmark flags>]\n");
printf("benchmark flags:\n");
int argc = 2;
char argv0[] = "init_benchmark";
char argv1[] = "--help";
char *argv[3] = { argv0, argv1, nullptr };
benchmark::Initialize(&argc, argv);
exit(1);
}
static void ShiftOptions(int argc, char **argv, std::vector<char *> *argvAfterShift)
{
(*argvAfterShift)[0] = argv[0];
for (int i = 1; i < argc; ++i) {
char *optarg = argv[i];
size_t index = 0;
// Find if musl defined this arg.
while (g_benchmarkLongOptions[index].name && strncmp(g_benchmarkLongOptions[index].name, optarg + 2, // 2 arg
strlen(g_benchmarkLongOptions[index].name))) {
++index;
}
// Not defined.
if (!g_benchmarkLongOptions[index].name) {
argvAfterShift->push_back(optarg);
} else if ((g_benchmarkLongOptions[index].has_arg == required_argument) && !strchr(optarg, '=')) {
i++;
}
}
argvAfterShift->push_back(nullptr);
}
static bench_opts_t ParseOptions(int argc, char **argv)
{
bench_opts_t opts;
int opt;
char *errorCheck = nullptr;
opterr = 0; // Don't show unrecognized option error.
while ((opt = getopt_long(argc, argv, "c:i:a:h", g_benchmarkLongOptions, nullptr)) != -1) {
switch (opt) {
case 'c':
if (!(*optarg)) {
printf("ERROR: no argument specified for init_cpu.\n");
PrintUsageAndExit();
break;
}
opts.cpuNum = strtol(optarg, &errorCheck, 10); // 10 base
if (*errorCheck) {
errx(1, "ERROR: Args %s is not a valid integer.", optarg);
}
break;
case 'i':
if (!(*optarg)) {
printf("ERROR: no argument specified for init_iterations.\n");
PrintUsageAndExit();
break;
}
opts.iterNum = strtol(optarg, &errorCheck, 10); // 10 base
if (*errorCheck != '\0' || opts.iterNum < 0) {
errx(1, "ERROR: Args %s is not a valid number of iterations.", optarg);
}
break;
case 'h':
PrintUsageAndExit();
break;
case '?':
break;
default:
exit(1);
}
}
return opts;
}
static void LockAndRun(benchmark::State &state, benchmark_func func, int cpuNum)
{
if (cpuNum >= 0) {
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(cpuNum, &cpuset);
if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0) {
printf("lock CPU failed, ERROR:%s\n", strerror(errno));
}
}
reinterpret_cast<void (*)(benchmark::State &)>(func)(state);
}
static args_vector *ResolveArgs(args_vector *argsVector, std::string args,
std::map<std::string, args_vector> &presetArgs)
{
// Get it from preset args.
if (presetArgs.count(args)) {
return &presetArgs[args];
}
// Convert string to int.
argsVector->push_back(std::vector<int64_t>());
std::stringstream sstream(args);
std::string arg;
while (sstream >> arg) {
char *errorCheck;
int converted = static_cast<int>(strtol(arg.c_str(), &errorCheck, 10)); // 10 base
if (*errorCheck) {
errx(1, "ERROR: Args str %s contains an invalid macro or int.", args.c_str());
}
(*argsVector)[0].push_back(converted);
}
return argsVector;
}
static args_vector GetArgs(const std::vector<int> &sizes)
{
args_vector args;
for (int size : sizes) {
args.push_back( {size} );
}
return args;
}
static args_vector GetArgs(const std::vector<int> &sizes, int value)
{
args_vector args;
for (int size : sizes) {
args.push_back( {size, value} );
}
return args;
}
static args_vector GetArgs(const std::vector<int> &sizes, int value1, int value2)
{
args_vector args;
for (int size : sizes) {
args.push_back( {size, value1, value2} );
}
return args;
}
static args_vector GetArgs(const std::vector<int> &sizes, const std::vector<int> &limits, int value)
{
args_vector args;
for (int size : sizes) {
for (int limit : limits) {
args.push_back( {size, limit, value} );
}
}
return args;
}
static std::map<std::string, args_vector> GetPresetArgs()
{
std::map<std::string, args_vector> presetArgs {
{"COMMON_ARGS", GetArgs(commonArgs)},
{"ALIGNED_ONEBUF", GetArgs(commonArgs, 0)},
{"ALIGNED_TWOBUF", GetArgs(commonArgs, 0, 0)},
{"STRING_LIMIT", GetArgs(commonArgs, limitSizes, 0)},
{"MATH_COMMON", args_vector{{0}, {1}, {2}, {3}, {4}, {5}}},
{"BENCHMARK_VARIABLE", args_vector{{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}}},
{"REALPATH_VARIABLE", args_vector{{0}, {1}, {2}, {3}, {4}}},
{"MMAP_SIZE", args_vector{{8}, {16}, {32}, {64}, {128}, {512}}},
};
return presetArgs;
}
static void RegisterSingleBenchmark(bench_opts_t opts, const std::string &funcName, args_vector *runArgs)
{
if (g_allBenchmarks.find(funcName) == g_allBenchmarks.end()) {
errx(1, "ERROR: No benchmark for function %s", funcName.c_str());
}
benchmark_func func = g_allBenchmarks.at(funcName).first;
for (const std::vector<int64_t> &args : (*runArgs)) {
// It will call LockAndRun(func, opts.cpuNum).
auto registration = benchmark::RegisterBenchmark(funcName.c_str(), LockAndRun, func, opts.cpuNum)->Args(args);
printf("opts.iterNum %ld \n", opts.iterNum);
if (opts.iterNum > 0) {
registration->Iterations(opts.iterNum);
}
}
}
static void RegisterAllBenchmarks(const bench_opts_t &opts, std::map<std::string, args_vector> &presetArgs)
{
for (auto &entry : g_allBenchmarks) {
auto &funcInfo = entry.second;
args_vector arg_vector;
args_vector *runArgs = ResolveArgs(&arg_vector, funcInfo.second, presetArgs);
RegisterSingleBenchmark(opts, entry.first, runArgs);
}
}
int main(int argc, char **argv)
{
std::map<std::string, args_vector> presetArgs = GetPresetArgs();
bench_opts_t opts = ParseOptions(argc, argv);
std::vector<char *> argvAfterShift(argc);
ShiftOptions(argc, argv, &argvAfterShift);
RegisterAllBenchmarks(opts, presetArgs);
if (setpriority(PRIO_PROCESS, 0, -20)) { // 20 max
perror("Set priority of process failed.\n");
}
CreateLocalParameterTest(512); // test max 512
int argcAfterShift = argvAfterShift.size();
benchmark::Initialize(&argcAfterShift, argvAfterShift.data());
benchmark::RunSpecifiedBenchmarks();
}