upload android base code part6

This commit is contained in:
August 2018-08-08 17:48:24 +08:00
parent 421e214c7d
commit 4e516ec6ed
35396 changed files with 9188716 additions and 0 deletions

View file

@ -0,0 +1,44 @@
#
# Copyright (C) 2016 The Android Open Source Project
#
# 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.
#
LOCAL_PATH := $(call my-dir)
# APCT build target for metrics tests
include $(CLEAR_VARS)
LOCAL_MODULE := netd_benchmark
LOCAL_CFLAGS := -Wall -Werror -Wunused-parameter
# Bug: http://b/29823425 Disable -Wvarargs for Clang update to r271374
LOCAL_CFLAGS += -Wno-varargs
EXTRA_LDLIBS := -lpthread
LOCAL_SHARED_LIBRARIES += libbase libbinder liblog libnetd_client
LOCAL_STATIC_LIBRARIES += libnetd_test_dnsresponder libutils
LOCAL_AIDL_INCLUDES := system/netd/server/binder
LOCAL_C_INCLUDES += system/netd/include \
system/netd/client \
system/netd/server \
system/netd/server/binder \
system/netd/tests/dns_responder \
bionic/libc/dns/include
LOCAL_SRC_FILES := main.cpp \
connect_benchmark.cpp \
dns_benchmark.cpp \
../../server/binder/android/net/metrics/INetdEventListener.aidl
LOCAL_MODULE_TAGS := eng tests
include $(BUILD_NATIVE_BENCHMARK)

View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2017 The Android Open Source Project
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.
-->
<configuration description="Config for netd_benchmark">
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="netd_benchmark->/data/local/tmp/netd_benchmark" />
</target_preparer>
<option name="test-suite-tag" value="apct" />
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="netd_benchmark" />
</test>
</configuration>

View file

@ -0,0 +1,72 @@
# NetD benchmarks
These are benchmarks for libc **connect** and **gethostbyname** functions as hooked by netd.
## Infrastructure
The benchmarks are powered by [google-benchmark](https://github.com/google/benchmark), which records
four statistics:
<table>
<tr>
<th>Statistic</th>
<th>Meaning</th>
</tr>
<tr>
<th>real_time</th>
<td>Mean wall-clock time taken for each iteration of the function under test to complete. This
includes any time spent in other processes.
<p>
Some of the **connect** benchmarks override this by implementing their own timings, but
the semantics are roughly the same. See connect_benchmark.cpp for details.</td>
</tr>
<tr>
<th>cpu_time</th>
<td>Mean time spent in the current thread during each iteration of the function under test. This
does not include any time spent in other processes or blocking on I/O.
<p>
Since almost all of the functionality we are testing here is in the netd server, not the
client, these timings are not relevant and should be ignored for most purposes.</td>
</tr>
<tr>
<th>iterations</th>
<td>The number of runs of the test function that were executed, across all threads, in order for
the test to reach the minimum amount of time run. Most tests here define 'minimum time run'
in terms of real time or 'manual time', rather than CPU time, for the reasons above.
<p>
This should be roughly inversely proportional to **real_time** for single-threaded
benchmarks and also somewhat proportional to the number of threads used.</td>
</tr>
<tr>
<th>label</th>
<td>Field that the benchmark can fill with an arbitrary string.
<p>
For graphing purposes, a few of the benchmarks in this directory store the 90th-percentile
latency in this field for comparison against the mean latency
(it's only possible to plot one other value apart from mean).
<p>
If the graphing ecosystem ever becomes advanced enough to plot multiple outputs from one
label, it might be more useful to log every decile to get a better picture of how spiky
things are.</td>
</table>
# Methods currently being benchmarked
## connect()
- Documented in [connect\_benchmark.cpp](connect_benchmark.cpp)
## getaddrinfo()
- Documented in [dns\_benchmark.cpp](dns_benchmark.cpp)
<style type="text/css">
tr:nth-child(2n+1) {
background: lightgrey;
}
td,th {
text-align: left;
vertical-align: top;
}
</style>

View file

@ -0,0 +1,349 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* 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.
*/
#define LOG_TAG "connect_benchmark"
/*
* See README.md for general notes.
*
* This set of benchmarks measures the throughput of connect() calls on a single thread for IPv4 and
* IPv6 under the following scenarios:
*
* - FWmark disabled (::ANDROID_NO_USE_FWMARK_CLIENT).
*
* The control case for other high load benchmarks. Essentially just testing performance of
* the kernel connect call. In real world use fwmark should stay on in order for traffic to
* be routed properly.
*
* - FWmark enabled only for metrics (::ANDROID_FWMARK_METRICS_ONLY).
*
* The default mode up to and including 7.1. Every time connect() is called on an AF_INET or
* AF_INET6 socket, netdclient sends a synchronous message to fwmarkserver to get the socket
* marked. Only the fields that are useful for marking or for metrics are sent in this mode;
* other fields are set to null for the RPC and ignored.
*
* - FWmark enabled for all events.
*
* The default mode starting from 7.1.2. As well as the normal connect() reporting, extra
* fields are filled in to log the IP and port of the connection.
*
* A second synchronous message is sent to fwmarkserver after the connection completes, to
* record latency. This message is forwarded to the system server over a oneway binder call.
*
* Realtime timed tests
* ====================
*
* The tests named *_high_load record the following useful information:
*
* - real_time: the mean roundtrip time for one connect() call under load
*
* - iterations: the number of times the test was run within the timelimit --- approximately
* MinTime / real_time
*
* Manually timed tests
* ====================
*
* All other sets of tests apart from *_high_load run with manual timing. The purpose of these is to
* measure 90th-percentile latency for connect() calls compared to mean latency.
*
* (TODO: ideally this should be against median latency, but google-benchmark only supports one
* custom 'label' output for graphing. Stddev isn't appropriate because the latency
* distribution is usually spiky, not in a nice neat normal-like distribution.)
*
* The manually timed tests record the following useful information:
*
* - real_time: the average time taken to complete a test run. Unlike the real_time used in high
* load tests, this is calculated from before-and-after values of the realtime clock
* over many iterations so may be less accurate than the under-load times.
*
* - iterations: the number of times the test was run within the timelimit --- approximately
* MinTime / real_time, although as explained, may not be as meaningful because of
* overhead from timing.
*
* - label: a manually-recorded time giving the 90th-percentile value of real_time over all
* individual runs. Should be compared to real_time.
*
*/
#include <arpa/inet.h>
#include <cutils/sockets.h>
#include <errno.h>
#include <netinet/in.h>
#include <time.h>
#include <map>
#include <functional>
#include <thread>
#include <android-base/stringprintf.h>
#include <benchmark/benchmark.h>
#include <log/log.h>
#include <utils/StrongPointer.h>
#include "FwmarkClient.h"
#include "SockDiag.h"
#include "Stopwatch.h"
#include "android/net/metrics/INetdEventListener.h"
using android::base::StringPrintf;
using android::net::metrics::INetdEventListener;
static int bindAndListen(int s) {
sockaddr_in6 sin6 = { .sin6_family = AF_INET6 };
if (bind(s, (sockaddr*) &sin6, sizeof(sin6)) == 0) {
if (listen(s, 1)) {
return -1;
}
sockaddr_in sin = {};
socklen_t len = sizeof(sin);
if (getsockname(s, (sockaddr*) &sin, &len)) {
return -1;
}
return ntohs(sin.sin_port);
} else {
return -1;
}
}
static void ipv4_loopback(benchmark::State& state, const bool waitBetweenRuns) {
const int listensocket = socket(AF_INET6, SOCK_STREAM, 0);
const int port = bindAndListen(listensocket);
if (port == -1) {
state.SkipWithError("Unable to bind server socket");
return;
}
// ALOGW("Listening on port = %d", port);
std::vector<uint64_t> latencies(state.max_iterations);
uint64_t iterations = 0;
while (state.KeepRunning()) {
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
state.SkipWithError(StringPrintf("socket() failed with errno=%d", errno).c_str());
break;
}
const Stopwatch stopwatch;
sockaddr_in server = { .sin_family = AF_INET, .sin_port = htons(port) };
if (connect(sock, (sockaddr*) &server, sizeof(server))) {
state.SkipWithError(StringPrintf("connect() failed with errno=%d", errno).c_str());
close(sock);
break;
}
if (waitBetweenRuns) {
latencies[iterations] = stopwatch.timeTaken() * 1e6L;
state.SetIterationTime(latencies[iterations] / 1e9L);
std::this_thread::sleep_for(std::chrono::milliseconds(10));
++iterations;
}
sockaddr_in6 client;
socklen_t clientlen = sizeof(client);
int accepted = accept(listensocket, (sockaddr *) &client, &clientlen);
if (accepted < 0) {
state.SkipWithError(StringPrintf("accept() failed with errno=%d", errno).c_str());
close(sock);
break;
}
close(accepted);
close(sock);
}
close(listensocket);
// ALOGI("Finished test on port = %d", port);
if (iterations > 0) {
latencies.resize(iterations);
sort(latencies.begin(), latencies.end());
state.SetLabel(StringPrintf("%lld", (long long) latencies[iterations * 9 / 10]));
}
}
static void ipv6_loopback(benchmark::State& state, const bool waitBetweenRuns) {
const int listensocket = socket(AF_INET6, SOCK_STREAM, 0);
const int port = bindAndListen(listensocket);
if (port == -1) {
state.SkipWithError("Unable to bind server socket");
return;
}
// ALOGW("Listening on port = %d", port);
std::vector<uint64_t> latencies(state.max_iterations);
uint64_t iterations = 0;
while (state.KeepRunning()) {
int sock = socket(AF_INET6, SOCK_STREAM, 0);
if (sock < 0) {
state.SkipWithError(StringPrintf("socket() failed with errno=%d", errno).c_str());
break;
}
const Stopwatch stopwatch;
sockaddr_in6 server = { .sin6_family = AF_INET6, .sin6_port = htons(port) };
if (connect(sock, (sockaddr*) &server, sizeof(server))) {
state.SkipWithError(StringPrintf("connect() failed with errno=%d", errno).c_str());
close(sock);
break;
}
if (waitBetweenRuns) {
latencies[iterations] = stopwatch.timeTaken() * 1e6L;
state.SetIterationTime(latencies[iterations] / 1e9L);
std::this_thread::sleep_for(std::chrono::milliseconds(10));
++iterations;
}
sockaddr_in6 client;
socklen_t clientlen = sizeof(client);
int accepted = accept(listensocket, (sockaddr *) &client, &clientlen);
if (accepted < 0) {
state.SkipWithError(StringPrintf("accept() failed with errno=%d", errno).c_str());
close(sock);
break;
}
close(accepted);
close(sock);
}
close(listensocket);
// ALOGI("Finished test on port = %d", port);
if (iterations > 0) {
latencies.resize(iterations);
sort(latencies.begin(), latencies.end());
state.SetLabel(StringPrintf("%lld", (long long) latencies[iterations * 9 / 10]));
}
}
static void run_at_reporting_level(decltype(ipv4_loopback) benchmarkFunction,
::benchmark::State& state, const int reportingLevel,
const bool waitBetweenRuns) {
// Our master thread (thread_index == 0) will control setup and teardown for other threads.
const bool isMaster = (state.thread_index == 0);
// Previous values of env variables used by fwmarkclient (only read/written by master thread)
const std::string savedSettings[] = {
FwmarkClient::ANDROID_NO_USE_FWMARK_CLIENT,
FwmarkClient::ANDROID_FWMARK_METRICS_ONLY
};
std::map<std::string, std::string> prevSettings;
// SETUP
if (isMaster) {
for (const auto setting : savedSettings) {
const char* prevEnvStr = getenv(setting.c_str());
if (prevEnvStr != nullptr) {
prevSettings[setting.c_str()] = prevEnvStr;
}
}
switch (reportingLevel) {
case INetdEventListener::REPORTING_LEVEL_NONE:
setenv(FwmarkClient::ANDROID_NO_USE_FWMARK_CLIENT, "", 1);
break;
case INetdEventListener::REPORTING_LEVEL_METRICS:
unsetenv(FwmarkClient::ANDROID_NO_USE_FWMARK_CLIENT);
setenv(FwmarkClient::ANDROID_FWMARK_METRICS_ONLY, "", 1);
break;
case INetdEventListener::REPORTING_LEVEL_FULL:
unsetenv(FwmarkClient::ANDROID_NO_USE_FWMARK_CLIENT);
unsetenv(FwmarkClient::ANDROID_FWMARK_METRICS_ONLY);
break;
}
}
// TEST
benchmarkFunction(state, waitBetweenRuns);
// TEARDOWN
if (isMaster) {
for (const auto setting : savedSettings) {
if (prevSettings.count(setting)) {
setenv(setting.c_str(), prevSettings[setting].c_str(), 1);
} else {
unsetenv(setting.c_str());
}
}
}
}
constexpr int MIN_THREADS = 1;
constexpr int MAX_THREADS = 1;
constexpr double MIN_TIME = 0.5 /* seconds */;
static void ipv4_metrics_reporting_no_fwmark(::benchmark::State& state) {
run_at_reporting_level(ipv4_loopback, state, INetdEventListener::REPORTING_LEVEL_NONE, true);
}
BENCHMARK(ipv4_metrics_reporting_no_fwmark)->MinTime(MIN_TIME)->UseManualTime();
// IPv4 metrics under low load
static void ipv4_metrics_reporting_no_load(::benchmark::State& state) {
run_at_reporting_level(ipv4_loopback, state, INetdEventListener::REPORTING_LEVEL_METRICS, true);
}
BENCHMARK(ipv4_metrics_reporting_no_load)->MinTime(MIN_TIME)->UseManualTime();
static void ipv4_full_reporting_no_load(::benchmark::State& state) {
run_at_reporting_level(ipv4_loopback, state, INetdEventListener::REPORTING_LEVEL_FULL, true);
}
BENCHMARK(ipv4_full_reporting_no_load)->MinTime(MIN_TIME)->UseManualTime();
// IPv4 benchmarks under high load
static void ipv4_metrics_reporting_high_load(::benchmark::State& state) {
run_at_reporting_level(ipv4_loopback, state, INetdEventListener::REPORTING_LEVEL_METRICS,
false);
}
BENCHMARK(ipv4_metrics_reporting_high_load)
->ThreadRange(MIN_THREADS, MAX_THREADS)->MinTime(MIN_TIME)->UseRealTime();
static void ipv4_full_reporting_high_load(::benchmark::State& state) {
run_at_reporting_level(ipv4_loopback, state, INetdEventListener::REPORTING_LEVEL_FULL, false);
}
BENCHMARK(ipv4_full_reporting_high_load)
->ThreadRange(MIN_THREADS, MAX_THREADS)->MinTime(MIN_TIME)->UseRealTime();
// IPv6 raw connect() without using fwmark
static void ipv6_metrics_reporting_no_fwmark(::benchmark::State& state) {
run_at_reporting_level(ipv6_loopback, state, INetdEventListener::REPORTING_LEVEL_NONE, true);
}
BENCHMARK(ipv6_metrics_reporting_no_fwmark)->MinTime(MIN_TIME)->UseManualTime();
// IPv6 metrics under low load
static void ipv6_metrics_reporting_no_load(::benchmark::State& state) {
run_at_reporting_level(ipv6_loopback, state, INetdEventListener::REPORTING_LEVEL_METRICS, true);
}
BENCHMARK(ipv6_metrics_reporting_no_load)->MinTime(MIN_TIME)->UseManualTime();
static void ipv6_full_reporting_no_load(::benchmark::State& state) {
run_at_reporting_level(ipv6_loopback, state, INetdEventListener::REPORTING_LEVEL_FULL, true);
}
BENCHMARK(ipv6_full_reporting_no_load)->MinTime(MIN_TIME)->UseManualTime();
// IPv6 benchmarks under high load
static void ipv6_metrics_reporting_high_load(::benchmark::State& state) {
run_at_reporting_level(ipv6_loopback, state, INetdEventListener::REPORTING_LEVEL_METRICS,
false);
}
BENCHMARK(ipv6_metrics_reporting_high_load)
->ThreadRange(MIN_THREADS, MAX_THREADS)->MinTime(MIN_TIME)->UseRealTime();
static void ipv6_full_reporting_high_load(::benchmark::State& state) {
run_at_reporting_level(ipv6_loopback, state, INetdEventListener::REPORTING_LEVEL_FULL, false);
}
BENCHMARK(ipv6_full_reporting_high_load)
->ThreadRange(MIN_THREADS, MAX_THREADS)->MinTime(MIN_TIME)->UseRealTime();

View file

@ -0,0 +1,194 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* 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.
*/
#define LOG_TAG "dns_benchmark"
/*
* See README.md for general notes.
*
* This set of benchmarks measures the throughput of getaddrinfo() on between 1 and 32 threads for
* the purpose of keeping track of the maximum load that netd can reasonably handle.
*
* The benchmark fixture runs in 3 different modes:
*
* - getaddrinfo_log_nothing
*
* The control case. Switches all kinds of DNS events reporting off and runs getaddrinfo() in a
* loop until the timer expires.
*
* This was the default and only mode in all versions before 7.0.
*
* - getaddrinfo_log_metrics
*
* DNS Logging Lite includes staple favourites such as event type (getaddrinfo/gethostbyname),
* return code, and latency, but misses out in-depth information such as resolved IP addresses.
*
* It is expected that this is a little slower than getaddrinfo_log_nothing because of the
* overhead, but not particularly worse, since it is a oneway binder call without too much data
* being sent per event.
*
* This was the default mode between versions 7.0 and 7.1 inclusive.
*
* - getaddrinfo_log_everything
*
* DNS Logging, in full HD, includes extra non-metrics fields such as hostname, a truncated
* list of resolved addresses, total resolved address count, and originating UID.
*
* Useful measurements
* ===================
*
* - real_time: the average time taken to make a single getaddrinfo lookup on a local DNS resolver
* run by DnsFixture. This will usually be higher on multithreaded tests as threads
* block on DNS lookups and Binder connections.
*
* - iterations: total number of runs finished within the time limit. Higher is better. This is
* roughly proportional to MinTime * nThreads / real_time.
*
*/
#include <netdb.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <android-base/stringprintf.h>
#include <benchmark/benchmark.h>
#include <utils/String16.h>
#include <utils/StrongPointer.h>
#include "dns_responder_client.h"
#include "NetdClient.h"
#include "android/net/metrics/INetdEventListener.h"
using android::base::StringPrintf;
using android::net::metrics::INetdEventListener;
constexpr int MIN_THREADS = 1;
constexpr int MAX_THREADS = 32;
class DnsFixture : public ::benchmark::Fixture {
protected:
static constexpr unsigned num_hosts = 1000;
DnsResponderClient dns;
std::vector<DnsResponderClient::Mapping> mappings;
std::vector<std::unique_ptr<test::DNSResponder>> mDns;
public:
void SetUp(const ::benchmark::State& state) override {
if (state.thread_index == 0) {
dns.SetUp();
std::vector<std::string> domains = { "example.com" };
std::vector<std::string> servers;
dns.SetupMappings(num_hosts, domains, &mappings);
dns.SetupDNSServers(MAXNS, mappings, &mDns, &servers);
const std::vector<int> mDefaultParams_Binder = { 300, 25, 8, 8 };
dns.SetResolversForNetwork(servers, domains, mDefaultParams_Binder);
}
}
void TearDown(const ::benchmark::State& state) override {
if (state.thread_index == 0) {
dns.ShutdownDNSServers(&mDns);
dns.TearDown();
}
}
std::vector<DnsResponderClient::Mapping> const& getMappings() const {
return mappings;
}
android::sp<android::net::INetd> getNetd() const {
return dns.mNetdSrv;
}
void getaddrinfo_until_done(benchmark::State &state) {
while (state.KeepRunning()) {
const uint32_t ofs = arc4random_uniform(getMappings().size());
const auto& mapping = getMappings()[ofs];
addrinfo* result = nullptr;
if (getaddrinfo(mapping.host.c_str(), nullptr, nullptr, &result)) {
state.SkipWithError(StringPrintf("getaddrinfo failed with errno=%d",
errno).c_str());
break;
}
if (result) {
freeaddrinfo(result);
result = nullptr;
}
}
}
void benchmark_at_reporting_level(benchmark::State &state, int metricsLevel) {
const bool isMaster = (state.thread_index == 0);
int oldMetricsLevel;
// SETUP
if (isMaster) {
auto rv = getNetd()->getMetricsReportingLevel(&oldMetricsLevel);
if (!rv.isOk()) {
state.SkipWithError(StringPrintf("Failed saving metrics reporting level: %s",
rv.toString8().string()).c_str());
return;
}
rv = getNetd()->setMetricsReportingLevel(metricsLevel);
if (!rv.isOk()) {
state.SkipWithError(StringPrintf("Failed changing metrics reporting: %s",
rv.toString8().string()).c_str());
return;
}
}
// TEST
getaddrinfo_until_done(state);
// TEARDOWN
if (isMaster) {
auto rv = getNetd()->setMetricsReportingLevel(oldMetricsLevel);
if (!rv.isOk()) {
state.SkipWithError(StringPrintf("Failed restoring metrics reporting level: %s",
rv.toString8().string()).c_str());
return;
}
}
}
};
// DNS calls without any metrics logged or sent.
BENCHMARK_DEFINE_F(DnsFixture, getaddrinfo_log_nothing)(benchmark::State& state) {
benchmark_at_reporting_level(state, INetdEventListener::REPORTING_LEVEL_NONE);
}
BENCHMARK_REGISTER_F(DnsFixture, getaddrinfo_log_nothing)
->ThreadRange(MIN_THREADS, MAX_THREADS)
->UseRealTime();
// DNS calls with metrics only (netId, latency, return code) sent to the system server.
BENCHMARK_DEFINE_F(DnsFixture, getaddrinfo_log_metrics)(benchmark::State& state) {
benchmark_at_reporting_level(state, INetdEventListener::REPORTING_LEVEL_METRICS);
}
BENCHMARK_REGISTER_F(DnsFixture, getaddrinfo_log_metrics)
->ThreadRange(MIN_THREADS, MAX_THREADS)
->UseRealTime();
// DNS calls with all information logged and sent to the system server.
BENCHMARK_DEFINE_F(DnsFixture, getaddrinfo_log_everything)(benchmark::State& state) {
benchmark_at_reporting_level(state, INetdEventListener::REPORTING_LEVEL_FULL);
}
BENCHMARK_REGISTER_F(DnsFixture, getaddrinfo_log_everything)
->ThreadRange(MIN_THREADS, MAX_THREADS)
->UseRealTime();

View file

@ -0,0 +1,19 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* 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>
BENCHMARK_MAIN();