diff options
author | Nikita Putikhin <nputikhin@google.com> | 2023-07-18 17:01:36 +0000 |
---|---|---|
committer | Nikita Putikhin <nputikhin@google.com> | 2023-07-19 14:07:11 +0000 |
commit | 3af7ce651f9fe85cdcf1ad6aeb16ab540f405fd3 (patch) | |
tree | 40484d205107060768313c24a81455ad16c38047 /libatrace_rust | |
parent | 01c69f9fbc561ba78ec7dbb4199775f8b3657b15 (diff) | |
download | extras-3af7ce651f9fe85cdcf1ad6aeb16ab540f405fd3.tar.gz |
Add a benchmark for libatrace_rust
The benchmark gives us data on relative performance of API wrappers vs
calling the API directly.
Right now it shows big overhead on atrace_begin with tracing disabled.
This is expected - we always allocate a CString which is ignored if
tracing is off. The perf issue will be fixed in the next commit.
Bug: 289989828
Test: Run benchmarks on aosp_cf_x86_64_phone
Change-Id: I25868b7724f70ac875ec1e8cbfb192e16cc7087c
Diffstat (limited to 'libatrace_rust')
-rw-r--r-- | libatrace_rust/benchmark/Android.bp | 37 | ||||
-rw-r--r-- | libatrace_rust/benchmark/README.md | 62 | ||||
-rw-r--r-- | libatrace_rust/benchmark/src/atrace_benchmark.cc | 61 | ||||
-rw-r--r-- | libatrace_rust/benchmark/src/atrace_benchmark.rs | 87 | ||||
-rw-r--r-- | libatrace_rust/benchmark/src/trace_enabler.cc | 37 | ||||
-rw-r--r-- | libatrace_rust/benchmark/src/trace_enabler.h | 36 |
6 files changed, 320 insertions, 0 deletions
diff --git a/libatrace_rust/benchmark/Android.bp b/libatrace_rust/benchmark/Android.bp new file mode 100644 index 00000000..7f219921 --- /dev/null +++ b/libatrace_rust/benchmark/Android.bp @@ -0,0 +1,37 @@ +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +rust_binary { + name: "libatrace_rust_benchmark", + srcs: ["src/atrace_benchmark.rs"], + rustlibs: [ + "libatrace_rust", + "libcriterion", + ], + static_libs: [ + "libatrace_benchmark_trace_enabler", + ], +} + +cc_binary { + name: "libatrace_rust_benchmark_cc", + srcs: ["src/atrace_benchmark.cc"], + shared_libs: [ + "libcutils", + "liblog", + ], + static_libs: [ + "libgoogle-benchmark-main", + "libatrace_benchmark_trace_enabler", + ], +} + +cc_library_static { + name: "libatrace_benchmark_trace_enabler", + srcs: ["src/trace_enabler.cc"], + shared_libs: [ + "libcutils", + "liblog", + ], +} diff --git a/libatrace_rust/benchmark/README.md b/libatrace_rust/benchmark/README.md new file mode 100644 index 00000000..c4e35fe0 --- /dev/null +++ b/libatrace_rust/benchmark/README.md @@ -0,0 +1,62 @@ +# libatrace_rust benchmarks + +Benchmarks to compare the performance of Rust ATrace bindings with directly calling the +`libcutils` methods from C++. + +There are two binaries implementing the same benchmarks: + +* `libatrace_rust_benchmark` (`atrace_benchmark.rs`) for Rust. +* `libatrace_rust_benchmark_cc` (`atrace_benchmark.cc`) for C++. + +The benchmarks emit ATrace events with tracing off and tracing on. `atrace_begin` is measured +with short and long event names to check if the string length affects timings. For example, +`tracing_on_begin/1000` measures `atrace_begin` with a 1000-character name and tracing enabled. + +## Running the benchmarks + +To run the benchmarks, push the binaries to the device with `adb` and launch them via `adb shell`. +You may need to push dynamic libraries they depend on as well if they're not present on device and +run with `LD_LIBRARY_PATH`. + +Do not enable ATrace collectors. The benchmarks effectively emit events in a loop and will spam +any trace and distort performance results. + +The benchmarks will override system properties to enable or disable events, specifically ATrace App +event collection in `debug.atrace.app_number` and `debug.atrace.app_0`. After a successful execution +the events will be disabled. + +## Results + +The timings are not representative of actual cost of fully enabling tracing, only of emitting +events via API, since there's nothing receiving the events. + +The tests were done on a `aosp_cf_x86_64_phone-userdebug` Cuttlefish VM. Execution times on real +device may be different but we expect similar relative performance between Rust wrappers and C. + +Rust results from `libatrace_rust_benchmark 2>&1 | grep time`: + +```text +tracing_off_begin/10 time: [91.195 ns 91.648 ns 92.193 ns] +tracing_off_begin/1000 time: [289.50 ns 290.57 ns 291.76 ns] +tracing_off_end time: [6.0455 ns 6.0998 ns 6.1644 ns] +tracing_on_begin/10 time: [1.2285 µs 1.2330 µs 1.2379 µs] +tracing_on_begin/1000 time: [1.4667 µs 1.4709 µs 1.4754 µs] +tracing_on_end time: [1.1344 µs 1.1444 µs 1.1543 µs] +``` + +C++ results from `libatrace_rust_benchmark_cc`: + +```text +------------------------------------------------------------------------ +Benchmark Time CPU Iterations +------------------------------------------------------------------------ +BM_TracingOffAtraceBegin/10 4.00 ns 3.96 ns 175953732 +BM_TracingOffAtraceBegin/1000 4.05 ns 4.02 ns 176298494 +BM_TracingOffAtraceEnd 4.08 ns 4.05 ns 176422059 +BM_TracingOnAtraceBegin/10 1119 ns 1110 ns 640816 +BM_TracingOnAtraceBegin/1000 1151 ns 1142 ns 615781 +BM_TracingOnAtraceEnd 1076 ns 1069 ns 653646 +``` + +*If you notice that measurements with tracing off and tracing on have similar times, it might mean +that enabling ATrace events failed and you need to debug the benchmark.* diff --git a/libatrace_rust/benchmark/src/atrace_benchmark.cc b/libatrace_rust/benchmark/src/atrace_benchmark.cc new file mode 100644 index 00000000..fa21638c --- /dev/null +++ b/libatrace_rust/benchmark/src/atrace_benchmark.cc @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2023 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> +#include <cutils/trace.h> +#include <string> + +#include "trace_enabler.h" + +static void BM_TracingOffAtraceBegin(benchmark::State& state) { + disable_app_atrace(); + std::string name(state.range(0), '0'); + for (auto _ : state) { + atrace_begin(ATRACE_TAG_APP, name.c_str()); + } +} + +static void BM_TracingOffAtraceEnd(benchmark::State& state) { + disable_app_atrace(); + for (auto _ : state) { + atrace_end(ATRACE_TAG_APP); + } +} + +static void BM_TracingOnAtraceBegin(benchmark::State& state) { + enable_atrace_for_single_app("*libatrace_rust_benchmark_cc"); + std::string name(state.range(0), '0'); + for (auto _ : state) { + atrace_begin(ATRACE_TAG_APP, name.c_str()); + } + disable_app_atrace(); +} + +static void BM_TracingOnAtraceEnd(benchmark::State& state) { + enable_atrace_for_single_app("*libatrace_rust_benchmark_cc"); + for (auto _ : state) { + atrace_end(ATRACE_TAG_APP); + } + disable_app_atrace(); +} + +// Register the function as a benchmark +BENCHMARK(BM_TracingOffAtraceBegin)->Arg(10)->Arg(1000); +BENCHMARK(BM_TracingOffAtraceEnd); +BENCHMARK(BM_TracingOnAtraceBegin)->Arg(10)->Arg(1000); +BENCHMARK(BM_TracingOnAtraceEnd); + +BENCHMARK_MAIN();
\ No newline at end of file diff --git a/libatrace_rust/benchmark/src/atrace_benchmark.rs b/libatrace_rust/benchmark/src/atrace_benchmark.rs new file mode 100644 index 00000000..30c492a5 --- /dev/null +++ b/libatrace_rust/benchmark/src/atrace_benchmark.rs @@ -0,0 +1,87 @@ +// Copyright (C) 2023 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. + +//! Benchmark for ATrace bindings. + +use atrace::AtraceTag; +use criterion::{BenchmarkId, Criterion}; + +extern "C" { + fn disable_app_atrace(); + fn enable_atrace_for_single_app(name: *const std::os::raw::c_char); +} + +fn turn_tracing_off() { + unsafe { + disable_app_atrace(); + } +} + +fn turn_tracing_on() { + let procname = std::ffi::CString::new(std::env::args().next().unwrap()).unwrap(); + unsafe { + enable_atrace_for_single_app(procname.as_ptr()); + } +} + +fn new_criterion() -> Criterion { + let path = "/data/local/tmp/criterion/benchmarks"; + std::fs::create_dir_all(path).unwrap_or_else(|e| { + panic!("The criterion folder should be possible to create at {}: {}", path, e) + }); + std::env::set_var("CRITERION_HOME", path); + Criterion::default() +} + +fn bench_tracing_off_begin(c: &mut Criterion, name_len: usize) { + turn_tracing_off(); + let name = "0".repeat(name_len); + c.bench_with_input(BenchmarkId::new("tracing_off_begin", name_len), &name, |b, name| { + b.iter(|| atrace::atrace_begin(AtraceTag::App, name.as_str())) + }); +} + +fn bench_tracing_off_end(c: &mut Criterion) { + turn_tracing_off(); + c.bench_function("tracing_off_end", |b| b.iter(|| atrace::atrace_end(AtraceTag::App))); +} + +fn bench_tracing_on_begin(c: &mut Criterion, name_len: usize) { + turn_tracing_on(); + let name = "0".repeat(name_len); + c.bench_with_input(BenchmarkId::new("tracing_on_begin", name_len), &name, |b, name| { + b.iter(|| atrace::atrace_begin(AtraceTag::App, name.as_str())) + }); + turn_tracing_off(); +} + +fn bench_tracing_on_end(c: &mut Criterion) { + turn_tracing_on(); + c.bench_function("tracing_on_end", |b| b.iter(|| atrace::atrace_end(AtraceTag::App))); + turn_tracing_off(); +} + +fn main() -> Result<(), Box<dyn std::error::Error>> { + let mut criterion = new_criterion(); + + bench_tracing_off_begin(&mut criterion, 10); + bench_tracing_off_begin(&mut criterion, 1000); + bench_tracing_off_end(&mut criterion); + + bench_tracing_on_begin(&mut criterion, 10); + bench_tracing_on_begin(&mut criterion, 1000); + bench_tracing_on_end(&mut criterion); + + Ok(()) +} diff --git a/libatrace_rust/benchmark/src/trace_enabler.cc b/libatrace_rust/benchmark/src/trace_enabler.cc new file mode 100644 index 00000000..49daff9b --- /dev/null +++ b/libatrace_rust/benchmark/src/trace_enabler.cc @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2023 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 "trace_enabler.h" + +#include <cutils/properties.h> +#include <cutils/trace.h> +#include <log/log.h> + +void set_property_or_die(const char* key, const char* value) { + LOG_ALWAYS_FATAL_IF(property_set(key, value) < 0, "Failed to set %s", key); +} + +void disable_app_atrace() { + set_property_or_die("debug.atrace.app_number", ""); + set_property_or_die("debug.atrace.app_0", ""); + atrace_update_tags(); +} + +void enable_atrace_for_single_app(const char* name) { + set_property_or_die("debug.atrace.app_number", "1"); + set_property_or_die("debug.atrace.app_0", name); + atrace_update_tags(); +} diff --git a/libatrace_rust/benchmark/src/trace_enabler.h b/libatrace_rust/benchmark/src/trace_enabler.h new file mode 100644 index 00000000..532c590e --- /dev/null +++ b/libatrace_rust/benchmark/src/trace_enabler.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2023 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. + */ + +#pragma once + +#include <sys/cdefs.h> + +// A library to enable tracing for benchmarks. +// It only causes ftrace events to be emitted so that we can measure +// performance and is not intended to enable tracing for meaningful results. + +__BEGIN_DECLS + +// Disable tracing for ATRACE_TAG_APP events. +// Terminates the app on error and writes an error message to logd and stderr. +void disable_app_atrace(); + +// Enable ATRACE_TAG_APP events only for the specified app pattern. +// ATrace uses fnmatch for the pattern. +// Terminates the app on error and writes an error message to logd and stderr. +void enable_atrace_for_single_app(const char* name); + +__END_DECLS
\ No newline at end of file |