summaryrefslogtreecommitdiffstats
path: root/eval
diff options
context:
space:
mode:
authorHåvard Pettersen <havardpe@oath.com>2022-02-24 13:05:19 +0000
committerHåvard Pettersen <havardpe@oath.com>2022-02-24 15:28:07 +0000
commitf690e3697625e94bed58450e849487f99a200261 (patch)
tree3ce82d065ea897247498d0214dd73bdb0700470f /eval
parent88cfafdd9e56d97f021061ad3f460689fda62567 (diff)
llvm stress test
Diffstat (limited to 'eval')
-rw-r--r--eval/CMakeLists.txt1
-rw-r--r--eval/src/tests/eval/llvm_stress/CMakeLists.txt8
-rw-r--r--eval/src/tests/eval/llvm_stress/llvm_stress_test.cpp128
3 files changed, 137 insertions, 0 deletions
diff --git a/eval/CMakeLists.txt b/eval/CMakeLists.txt
index e6669e3fde8..ff731158b21 100644
--- a/eval/CMakeLists.txt
+++ b/eval/CMakeLists.txt
@@ -29,6 +29,7 @@ vespa_define_module(
src/tests/eval/inline_operation
src/tests/eval/int8float
src/tests/eval/interpreted_function
+ src/tests/eval/llvm_stress
src/tests/eval/multiply_add
src/tests/eval/nested_loop
src/tests/eval/node_tools
diff --git a/eval/src/tests/eval/llvm_stress/CMakeLists.txt b/eval/src/tests/eval/llvm_stress/CMakeLists.txt
new file mode 100644
index 00000000000..2c735666b62
--- /dev/null
+++ b/eval/src/tests/eval/llvm_stress/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(eval_llvm_stress_test_app TEST
+ SOURCES
+ llvm_stress_test.cpp
+ DEPENDS
+ vespaeval
+)
+vespa_add_test(NAME eval_llvm_stress_test_app NO_VALGRIND COMMAND eval_llvm_stress_test_app)
diff --git a/eval/src/tests/eval/llvm_stress/llvm_stress_test.cpp b/eval/src/tests/eval/llvm_stress/llvm_stress_test.cpp
new file mode 100644
index 00000000000..ed1fbaf3f4d
--- /dev/null
+++ b/eval/src/tests/eval/llvm_stress/llvm_stress_test.cpp
@@ -0,0 +1,128 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include <vespa/vespalib/testkit/test_kit.h>
+#include <vespa/eval/eval/function.h>
+#include <vespa/eval/eval/llvm/compiled_function.h>
+#include <vespa/vespalib/util/stringfmt.h>
+#include <vespa/vespalib/util/time.h>
+#include <vespa/vespalib/util/size_literals.h>
+#include <random>
+
+using vespalib::make_string_short::fmt;
+using namespace vespalib;
+using namespace vespalib::eval;
+
+//-----------------------------------------------------------------------------
+// This test will stress llvm compilation by performing multiple
+// compilations concurrently to try to uncover any potential races
+// that could lead to memory overwrites. Run manually for best
+// results.
+// -----------------------------------------------------------------------------
+
+duration budget = duration::zero();
+size_t expr_size = 1;
+
+//-----------------------------------------------------------------------------
+
+struct Opts {
+ char **arg;
+ char **end;
+ Opts(int argc, char **argv) : arg(argv), end(arg + argc) {
+ if (arg != end) {
+ ++arg; // skip self
+ }
+ }
+ int get_int(const char *name, int fallback) {
+ int value = fallback;
+ if (arg != end) {
+ value = atoi(*arg);
+ fprintf(stderr, "%s: %d (<- '%s')\n", name, value, *arg);
+ ++arg;
+ } else {
+ fprintf(stderr, "%s: %d (default)\n", name, value);
+ }
+ return value;
+ }
+};
+
+struct Done {
+ steady_time end_time;
+ Done(duration how_long) : end_time() { reset(how_long); }
+ void reset(duration how_long) { end_time = steady_clock::now() + how_long; }
+ bool operator()() const { return steady_clock::now() >= end_time; }
+};
+
+struct Rnd {
+ std::mt19937 gen;
+ Rnd(size_t seed) : gen(seed) {}
+ size_t get_int(size_t min, size_t max) {
+ std::uniform_int_distribution<size_t> dist(min, max);
+ return dist(gen);
+ }
+};
+
+vespalib::string make_expr(size_t size, Rnd &rnd) {
+ if (size < 2) {
+ auto x = rnd.get_int(0, 99);
+ if (x < 2) {
+ return "0";
+ } else if (x < 10) {
+ return "0.75";
+ } else if (x < 18) {
+ return "1";
+ } else if (x < 26) {
+ return "1.25";
+ } else {
+ static vespalib::string params("abcdefghijk");
+ auto idx = rnd.get_int(0, params.size() - 1);
+ return params.substr(idx, 1);
+ }
+ } else {
+ auto x = rnd.get_int(0, 99);
+ if ((x < 80) || (size < 3)) {
+ auto left = rnd.get_int(1, size - 1);
+ auto right = size - left;
+ if (x < 40) {
+ return "(" + make_expr(left, rnd) + "+" + make_expr(right, rnd) + ")";
+ } else {
+ return "(" + make_expr(left, rnd) + "*" + make_expr(right, rnd) + ")";
+ }
+ } else {
+ auto cond = rnd.get_int(1, size - 2);
+ auto left = rnd.get_int(1, size - cond - 1);
+ auto right = size - cond - left;
+ return "if(" + make_expr(cond, rnd) + "," + make_expr(left, rnd) + "," + make_expr(right, rnd) + ")";
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+TEST_MT_F("stress test llvm compilation", 64, Done(budget)) {
+ size_t my_seed = 5489u + (123 * thread_id);
+ Rnd rnd(my_seed);
+ const auto &done = f1;
+ auto my_expr = make_expr(expr_size, rnd);
+ if ((thread_id == 0) && (my_expr.size() < 128)) {
+ fprintf(stderr, "example expression: %s\n", my_expr.c_str());
+ }
+ auto my_fun = Function::parse(my_expr);
+ ASSERT_TRUE(!my_fun->has_error());
+ while (!done()) {
+ CompiledFunction arr_cf(*my_fun, PassParams::ARRAY);
+ CompiledFunction lazy_cf(*my_fun, PassParams::LAZY);
+ std::thread([my_fun]{ CompiledFunction my_arr_cf(*my_fun, PassParams::ARRAY); }).join();
+ std::thread([my_fun]{ CompiledFunction my_lazy_cf(*my_fun, PassParams::LAZY); }).join();
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+int main(int argc, char **argv) {
+ TEST_MASTER.init(__FILE__);
+ Opts opts(argc, argv);
+ budget = 1s * opts.get_int("seconds to run", 1);
+ expr_size = opts.get_int("expression size", 16);
+ TEST_RUN_ALL();
+ return (TEST_MASTER.fini() ? 0 : 1);
+}