Files
scylladb/test/boost/wasm_test.cc
Avi Kivity f3eade2f62 treewide: relicense to ScyllaDB-Source-Available-1.0
Drop the AGPL license in favor of a source-available license.
See the blog post [1] for details.

[1] https://www.scylladb.com/2024/12/18/why-were-moving-to-a-source-available-license/
2024-12-18 17:45:13 +02:00

104 lines
3.4 KiB
C++

/*
* Copyright (C) 2022-present ScyllaDB
*/
/*
* SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0
*/
#include "lang/wasm.hh"
#include "lang/wasm_instance_cache.hh"
#include "rust/wasmtime_bindings.hh"
#include <seastar/coroutine/maybe_yield.hh>
#include <chrono>
#include <seastar/core/lowres_clock.hh>
#include "test/lib/scylla_test_case.hh"
#include <seastar/core/coroutine.hh>
SEASTAR_TEST_CASE(test_long_udf_yields) {
auto wasm_engine = wasmtime::create_engine(1024 * 1024);
wasm::alien_thread_runner alien_runner;
auto wasm_cache = std::make_unique<wasm::instance_cache>(100 * 1024 * 1024, 1024 * 1024, std::chrono::seconds(1));
auto wasm_ctx = wasm::context(*wasm_engine, "fib", *wasm_cache, 100000, 100000000000);
// Recursive fibonacci function
co_await wasm::precompile(alien_runner, wasm_ctx, {}, R"(
(module
(type (;0;) (func (param i64) (result i64)))
(func (;0;) (type 0) (param i64) (result i64)
(local i64 i32)
local.get 0
i64.const 2
i64.lt_s
if ;; label = @1
local.get 0
return
end
loop ;; label = @1
local.get 0
i64.const 1
i64.sub
call 0
local.get 1
i64.add
local.set 1
local.get 0
i64.const 3
i64.gt_s
local.get 0
i64.const 2
i64.sub
local.set 0
br_if 0 (;@1;)
end
local.get 0
local.get 1
i64.add)
(func (;1;) (type 0) (param i64) (result i64)
local.get 0
call 0)
(memory (;0;) 2)
(global (;0;) i32 (i32.const 1024))
(export "memory" (memory 0))
(export "fib" (func 1))
(export "_scylla_abi" (global 0))
(data (;0;) (i32.const 1024) "01"))
)");
wasm_ctx.module.value()->compile(*wasm_engine);
auto argv = wasmtime::get_val_vec();
argv->push_i64(42);
auto rets = wasmtime::get_val_vec();
rets->push_i32(0);
auto store = wasmtime::create_store(wasm_ctx.engine_ptr, wasm_ctx.total_fuel, wasm_ctx.yield_fuel);
auto instance = wasmtime::create_instance(wasm_ctx.engine_ptr, **wasm_ctx.module, *store);
auto func = wasmtime::create_func(*instance, *store, wasm_ctx.function_name);
auto memory = wasmtime::get_memory(*instance, *store);
auto fut = wasmtime::get_func_future(*store, *func, *argv, *rets);
bool stop = false;
using namespace std::chrono;
auto max_duration = duration(nanoseconds(0));
auto steps = 0;
while (!stop) {
auto start = system_clock::now();
timespec cpu_start;
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &cpu_start);
stop = fut->resume();
timespec cpu_end;
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &cpu_end);
auto cpu_duration = duration_cast<nanoseconds>(seconds(cpu_end.tv_sec) + nanoseconds(cpu_end.tv_nsec) - seconds(cpu_start.tv_sec) - nanoseconds(cpu_start.tv_nsec));
auto curr_duration = system_clock::now() - start;
if (duration_cast<microseconds>(curr_duration).count() < duration_cast<microseconds>(cpu_duration).count() * 10) {
// If the wall clock time is too much bigger than the cpu time, the machine is probably overloaded
// and we don't want to count this as a valid measurement
max_duration = std::max(max_duration, curr_duration);
}
++steps;
}
BOOST_REQUIRE(max_duration < duration(milliseconds(100)));
BOOST_REQUIRE(steps > 1);
BOOST_CHECK_EQUAL(rets->pop_val()->i64(), 267914296);
co_return;
}