summaryrefslogtreecommitdiff
path: root/libatrace_rust
diff options
context:
space:
mode:
authorNikita Putikhin <nputikhin@google.com>2023-07-18 17:01:36 +0000
committerNikita Putikhin <nputikhin@google.com>2023-07-19 14:07:11 +0000
commit3af7ce651f9fe85cdcf1ad6aeb16ab540f405fd3 (patch)
tree40484d205107060768313c24a81455ad16c38047 /libatrace_rust
parent01c69f9fbc561ba78ec7dbb4199775f8b3657b15 (diff)
downloadextras-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.bp37
-rw-r--r--libatrace_rust/benchmark/README.md62
-rw-r--r--libatrace_rust/benchmark/src/atrace_benchmark.cc61
-rw-r--r--libatrace_rust/benchmark/src/atrace_benchmark.rs87
-rw-r--r--libatrace_rust/benchmark/src/trace_enabler.cc37
-rw-r--r--libatrace_rust/benchmark/src/trace_enabler.h36
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