yams/tests/benchmarks/entity_extraction_bench.cpp
Trevon 577adf1e0f
build: standardize the Debug build dir on build/debug (#248)
* build: standardize the Debug build dir on build/debug

`docs/BUILD.md` and `AGENTS.md` document `./setup.sh Debug` producing
`build/debug`, but `setup.sh`/`setup.ps1` created `builddir` and `.clangd`
pointed there too, so the documented layout and the actual tree disagreed.

Align the Debug mapping with the documented layout:
- setup.sh / setup.ps1: Debug -> `build/debug`
- CMakeLists.txt: Debug `_meson_build_dir` -> `build/debug`
- .clangd: CompilationDatabase -> `build/debug`
- plugin test fallbacks, S3 smoke default, quality-gate candidate list, and
  doc examples -> `build/debug`

Legacy `builddir` trees stay readable: the quality gate and local-ci scripts
still probe `builddir` as a fallback, and `plugin_trust` already treats
`/build/` paths as build artifacts.

* build: migrate remaining Debug consumers off builddir

Follow-up to the Debug build-dir standardization: tracked consumers still
hardcoded `builddir` and would break or silently skip against a fresh
`build/debug` tree. Migrate them, keeping tolerant fallbacks where a legacy
tree may still exist.

- CI: `.github/workflows/tests.yml` runs `./setup.sh Debug` and then compiled
  `-C builddir`; switch BUILD_DIR/COMPILE_DB_DIR/compile paths to `build/debug`.
  Same for windows-test-diagnose.yml.
- IDE: `.vscode/tasks.json` build/test/bench tasks target `build/debug`.
- Runtime: `object_storage_plugin_loader` also probes `build/debug/plugins`
  (and the flat `build/debug`), retaining the `builddir` fallbacks.
- Tests/docs: ONNX tuning integration plugin dir, benchmarks, and plugin
  READMEs/examples use `build/debug`.

`./build/*` is already excluded from the quality-gate find and `.dockerignore`,
so no exclusion lists change.
2026-10-01 08:45:20 -06:00

164 lines
5 KiB
C++

#include <benchmark/benchmark.h>
#include <cstring>
#include <optional>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>
#include <yams/compat/dlfcn.h>
extern "C" {
#include <yams/plugins/abi.h>
#include <yams/plugins/entity_extractor_v2.h>
}
namespace {
struct GlintPluginAPI {
void* handle{};
yams_entity_extractor_v2* api{};
GlintPluginAPI() = default;
GlintPluginAPI(const GlintPluginAPI&) = delete;
GlintPluginAPI& operator=(const GlintPluginAPI&) = delete;
GlintPluginAPI(GlintPluginAPI&&) noexcept = default;
GlintPluginAPI& operator=(GlintPluginAPI&&) noexcept = default;
~GlintPluginAPI() {
// Avoid dlclose during benchmark teardown; plugin tests use same pattern.
}
};
std::optional<GlintPluginAPI> loadGlintPlugin() {
GlintPluginAPI p;
#ifdef __APPLE__
const char* candidates[] = {
"build/debug/plugins/glint/yams_glint.dylib",
"build/debug/plugins/glint/yams_glint.dylib",
"plugins/glint/yams_glint.dylib",
};
#elif defined(_WIN32)
const char* candidates[] = {
"build/debug/plugins/glint/yams_glint.dll",
"build/debug/plugins/glint/yams_glint.dll",
"plugins/glint/yams_glint.dll",
};
#else
const char* candidates[] = {
"build/debug/plugins/glint/yams_glint.so",
"build/debug/plugins/glint/yams_glint.so",
"plugins/glint/yams_glint.so",
};
#endif
for (const char* path : candidates) {
p.handle = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
if (!p.handle) {
continue;
}
auto getiface = reinterpret_cast<int (*)(const char*, uint32_t, void**)>(
dlsym(p.handle, "yams_plugin_get_interface"));
auto init = reinterpret_cast<int (*)(const char*, const void*)>(
dlsym(p.handle, "yams_plugin_init"));
if (!getiface || !init) {
continue;
}
if (init(nullptr, nullptr) != 0) {
continue;
}
void* ptr = nullptr;
int rc =
getiface(YAMS_IFACE_ENTITY_EXTRACTOR_V2, YAMS_IFACE_ENTITY_EXTRACTOR_V2_VERSION, &ptr);
if (rc == 0 && ptr) {
p.api = reinterpret_cast<yams_entity_extractor_v2*>(ptr);
std::optional<GlintPluginAPI> out;
out.emplace(std::move(p));
return out;
}
}
return std::nullopt;
}
GlintPluginAPI& plugin() {
static auto loaded = loadGlintPlugin();
if (!loaded || !loaded->api) {
throw std::runtime_error("glint plugin not available");
}
return *loaded;
}
std::string makeText(std::size_t repeats) {
std::string text;
text.reserve(repeats * 96);
for (std::size_t i = 0; i < repeats; ++i) {
text += "Albert Einstein developed relativity at Princeton while Google hired Ada Lovelace "
"in 1998. ";
}
return text;
}
void BM_GlintSupportsTextPlain(benchmark::State& state) {
auto& p = plugin();
for (auto _ : state) {
benchmark::DoNotOptimize(p.api->supports(p.api->self, "text/plain"));
}
}
void BM_GlintExtractShortText(benchmark::State& state) {
auto& p = plugin();
static const std::string text = makeText(1);
for (auto _ : state) {
yams_entity_extraction_result_v2* result = nullptr;
int rc = p.api->extract(p.api->self, text.data(), text.size(), nullptr, &result);
benchmark::DoNotOptimize(rc);
if (result) {
benchmark::DoNotOptimize(result->entity_count);
p.api->free_result(p.api->self, result);
}
}
state.SetBytesProcessed(static_cast<int64_t>(state.iterations() * text.size()));
}
void BM_GlintExtractMediumText(benchmark::State& state) {
auto& p = plugin();
static const std::string text = makeText(8);
for (auto _ : state) {
yams_entity_extraction_result_v2* result = nullptr;
int rc = p.api->extract(p.api->self, text.data(), text.size(), nullptr, &result);
benchmark::DoNotOptimize(rc);
if (result) {
benchmark::DoNotOptimize(result->entity_count);
p.api->free_result(p.api->self, result);
}
}
state.SetBytesProcessed(static_cast<int64_t>(state.iterations() * text.size()));
}
void BM_GlintExtractLongText(benchmark::State& state) {
auto& p = plugin();
static const std::string text = makeText(32);
for (auto _ : state) {
yams_entity_extraction_result_v2* result = nullptr;
int rc = p.api->extract(p.api->self, text.data(), text.size(), nullptr, &result);
benchmark::DoNotOptimize(rc);
if (result) {
benchmark::DoNotOptimize(result->entity_count);
p.api->free_result(p.api->self, result);
}
}
state.SetBytesProcessed(static_cast<int64_t>(state.iterations() * text.size()));
}
} // namespace
BENCHMARK(BM_GlintSupportsTextPlain)->Unit(benchmark::kNanosecond);
BENCHMARK(BM_GlintExtractShortText)->Unit(benchmark::kMicrosecond);
BENCHMARK(BM_GlintExtractMediumText)->Unit(benchmark::kMicrosecond);
BENCHMARK(BM_GlintExtractLongText)->Unit(benchmark::kMicrosecond);
BENCHMARK_MAIN();