summaryrefslogtreecommitdiff
path: root/libcxx/test/benchmarks
diff options
context:
space:
mode:
Diffstat (limited to 'libcxx/test/benchmarks')
-rw-r--r--libcxx/test/benchmarks/containers/associative/associative_container_benchmarks.h43
-rw-r--r--libcxx/test/benchmarks/spec.gen.py78
-rw-r--r--libcxx/test/benchmarks/streams/ofstream.bench.cpp25
3 files changed, 146 insertions, 0 deletions
diff --git a/libcxx/test/benchmarks/containers/associative/associative_container_benchmarks.h b/libcxx/test/benchmarks/containers/associative/associative_container_benchmarks.h
index 535a52f0a08a..b39569812640 100644
--- a/libcxx/test/benchmarks/containers/associative/associative_container_benchmarks.h
+++ b/libcxx/test/benchmarks/containers/associative/associative_container_benchmarks.h
@@ -259,6 +259,49 @@ void associative_container_benchmarks(std::string container) {
}
});
+ if constexpr (is_map_like && !is_multi_key_container) {
+ bench("insert_or_assign(key, value) (already present)", [=](auto& st) {
+ const std::size_t size = st.range(0) ? st.range(0) : 1;
+ std::vector<Value> in = make_value_types(generate_unique_keys(size));
+ Value to_insert = in[in.size() / 2]; // pick any existing value
+ std::vector<Container> c(BatchSize, Container(in.begin(), in.end()));
+ typename Container::iterator inserted[BatchSize];
+
+ while (st.KeepRunningBatch(BatchSize)) {
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ inserted[i] =
+ adapt_operations<Container>::get_iterator(c[i].insert_or_assign(to_insert.first, to_insert.second));
+ benchmark::DoNotOptimize(inserted[i]);
+ benchmark::DoNotOptimize(c[i]);
+ benchmark::ClobberMemory();
+ }
+ }
+ });
+
+ bench("insert_or_assign(key, value) (new value)", [=](auto& st) {
+ const std::size_t size = st.range(0);
+ std::vector<Value> in = make_value_types(generate_unique_keys(size + 1));
+ Value to_insert = in.back();
+ in.pop_back();
+ std::vector<Container> c(BatchSize, Container(in.begin(), in.end()));
+
+ while (st.KeepRunningBatch(BatchSize)) {
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ auto result = c[i].insert_or_assign(to_insert.first, to_insert.second);
+ benchmark::DoNotOptimize(result);
+ benchmark::DoNotOptimize(c[i]);
+ benchmark::ClobberMemory();
+ }
+
+ st.PauseTiming();
+ for (std::size_t i = 0; i != BatchSize; ++i) {
+ c[i].erase(get_key(to_insert));
+ }
+ st.ResumeTiming();
+ }
+ });
+ }
+
// The insert(hint, ...) methods are only relevant for ordered containers, and we lack
// a good way to compute a hint for unordered ones.
if constexpr (is_ordered_container) {
diff --git a/libcxx/test/benchmarks/spec.gen.py b/libcxx/test/benchmarks/spec.gen.py
new file mode 100644
index 000000000000..b4b31d4e3687
--- /dev/null
+++ b/libcxx/test/benchmarks/spec.gen.py
@@ -0,0 +1,78 @@
+# ===----------------------------------------------------------------------===##
+#
+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+# ===----------------------------------------------------------------------===##
+
+# REQUIRES: enable-spec-benchmarks
+
+# RUN: mkdir -p %T
+# RUN: echo "%{cxx}" > %T/cxx.subs
+# RUN: echo "%{compile_flags}" > %T/compile_flags.subs
+# RUN: echo "%{flags}" > %T/flags.subs
+# RUN: echo "%{link_flags}" > %T/link_flags.subs
+# RUN: echo "%{spec_dir}" > %T/spec_dir.subs
+# RUN: %{python} %s %T
+# END.
+
+import json
+import pathlib
+import sys
+
+test_dir = pathlib.Path(sys.argv[1])
+cxx = (test_dir / 'cxx.subs').open().read().strip()
+compile_flags = (test_dir / 'compile_flags.subs').open().read().strip()
+flags = (test_dir / 'flags.subs').open().read().strip()
+link_flags = (test_dir / 'link_flags.subs').open().read().strip()
+spec_dir = pathlib.Path((test_dir / 'spec_dir.subs').open().read().strip())
+
+# Setup the configuration file
+test_dir.mkdir(parents=True, exist_ok=True)
+spec_config = test_dir / 'spec-config.cfg'
+spec_config.write_text(f"""
+default:
+ ignore_errors = 1
+ iterations = 1
+ label = spec-stdlib
+ log_line_width = 4096
+ makeflags = --jobs=8
+ mean_anyway = 1
+ output_format = csv
+ preenv = 0
+ reportable = 0
+ tune = base
+ copies = 1
+ threads = 1
+ CC = cc -O3
+ CXX = {cxx} {compile_flags} {flags} {link_flags} -Wno-error
+ CC_VERSION_OPTION = --version
+ CXX_VERSION_OPTION = --version
+ EXTRA_PORTABILITY = -DSPEC_NO_CXX17_SPECIAL_MATH_FUNCTIONS # because libc++ doesn't implement the special math functions yet
+""")
+
+# Build the list of benchmarks. We take all intrate and fprate benchmarks that contain C++ and
+# discard the ones that contain Fortran, since this test suite isn't set up to build Fortran code.
+spec_benchmarks = set()
+no_fortran = set()
+with open(spec_dir / 'benchspec' / 'CPU' / 'intrate_any_cpp.bset', 'r') as f:
+ spec_benchmarks.update(json.load(f)['benchmarks'])
+with open(spec_dir / 'benchspec' / 'CPU' / 'fprate_any_cpp.bset', 'r') as f:
+ spec_benchmarks.update(json.load(f)['benchmarks'])
+with open(spec_dir / 'benchspec' / 'CPU' / 'no_fortran.bset', 'r') as f:
+ no_fortran.update(json.load(f)['benchmarks'])
+spec_benchmarks &= no_fortran
+
+for benchmark in spec_benchmarks:
+ print(f'#--- {benchmark}.sh.test')
+ print(f'RUN: rm -rf %T') # clean up any previous (potentially incomplete) run
+ print(f'RUN: mkdir %T')
+ print(f'RUN: cp {spec_config} %T/spec-config.cfg')
+ print(f'RUN: %{{spec_dir}}/bin/runcpu --config %T/spec-config.cfg --size train --output-root %T --rebuild {benchmark}')
+ print(f'RUN: rm -rf %T/benchspec') # remove the temporary directory, which can become quite large
+
+ # Parse the results into a LNT-compatible format. This also errors out if there are no CSV files, which
+ # means that the benchmark didn't run properly (the `runcpu` command above never reports a failure).
+ print(f'RUN: %{{libcxx-dir}}/utils/parse-spec-results %T/result/*.train.csv --output-format=lnt > %T/results.lnt')
+ print(f'RUN: cat %T/results.lnt')
diff --git a/libcxx/test/benchmarks/streams/ofstream.bench.cpp b/libcxx/test/benchmarks/streams/ofstream.bench.cpp
new file mode 100644
index 000000000000..60606a9d67e2
--- /dev/null
+++ b/libcxx/test/benchmarks/streams/ofstream.bench.cpp
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include <fstream>
+#include <vector>
+
+#include <benchmark/benchmark.h>
+
+static void bm_write(benchmark::State& state) {
+ std::vector<char> buffer;
+ buffer.resize(16384);
+
+ std::ofstream stream("/dev/null");
+
+ for (auto _ : state)
+ stream.write(buffer.data(), buffer.size());
+}
+BENCHMARK(bm_write);
+
+BENCHMARK_MAIN();