Add benchmarks for heap size retrieval
Add benchmarks for mallinfo, and for retrieving RSS from
/proc/self/statm, since we're considering using these for GC
triggering.
Add some static linkage specifiers, after running into a build
problem due to a spurious conflict.
Bug: 111447610
Test: Ran benchmarks
Change-Id: Ie50d512294993882728c63ce51ec507590257d80
diff --git a/benchmarks/get_heap_size_benchmark.cpp b/benchmarks/get_heap_size_benchmark.cpp
new file mode 100644
index 0000000..c3680dc
--- /dev/null
+++ b/benchmarks/get_heap_size_benchmark.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+// This measures the time required to compute two different native heap size metrics that
+// we might use to guide GC triggering.
+
+#include <atomic>
+#include <err.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <pthread.h>
+#include <sched.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <benchmark/benchmark.h>
+#include "util.h"
+
+static volatile size_t sink;
+
+static constexpr int NTHREADS = 5;
+
+static std::atomic<int> thread_count;
+
+static void* thread_func(void* arg) {
+ *reinterpret_cast<void**>(arg) = malloc(17);
+ thread_count++;
+ return nullptr;
+}
+
+static void BM_mallinfo(benchmark::State& state) {
+ pthread_t t[NTHREADS];
+ void* object[NTHREADS];
+ // Create threads to populate thread-local arenas, if any.
+ thread_count = 0;
+ for (int i = 0; i < 5; i++) {
+ int res = pthread_create(t + i, NULL, thread_func, object + i);
+ if (res != 0) {
+ errx(1, "ERROR: pthread_create failed");
+ }
+ }
+ while (thread_count != NTHREADS) {
+ sched_yield();
+ }
+ for (auto _ : state) {
+ sink = mallinfo().uordblks;
+ }
+ for (int i = 0; i < 5; i++) {
+ int res = pthread_join(t[i], NULL);
+ if (res != 0) {
+ errx(1, "ERROR: pthread_join failed");
+ }
+ free(object[i]);
+ }
+}
+
+BIONIC_BENCHMARK(BM_mallinfo);
+
+static constexpr int BUF_SIZE = 100;
+
+static void BM_read_statm(benchmark::State& state) {
+ char buf[BUF_SIZE];
+ int statm_fd = open("/proc/self/statm", O_RDONLY);
+ if (statm_fd == -1) {
+ errx(1, "ERROR: Open failed");
+ }
+ for (auto _ : state) {
+ off_t result = lseek(statm_fd, 0 /* offset */, SEEK_SET);
+ if (result == (off_t) -1) {
+ errx(1, "ERROR: lseek to beginning failed");
+ }
+ ssize_t nread = read(statm_fd, buf, BUF_SIZE);
+ if (nread < 13 || nread > 50) {
+ errx(1, "ERROR: Implausible read result; result = %zd", nread);
+ }
+ // We should really add the parsing overhead for the result; but that should be < 100 nsecs
+ // if we tweak it enough.
+ }
+ if (close(statm_fd) == -1) {
+ errx(1, "ERROR: Close failed");
+ }
+}
+
+BIONIC_BENCHMARK(BM_read_statm);