Some checks failed
Fuzz Smoke / libFuzzer smoke (push) Has been cancelled
* chore(warnings): default-initialize aggregate members left out of brace-init
GCC -Wmissing-field-initializers fired about 1300 times where tests and
src build structs with a short positional brace list. Give the omitted
members an empty default member initializer. Value-initialization from
{} is what aggregate init already did for them, so behavior is
unchanged.
Signed-off-by: trvon <me@trevon.dev>
* chore(warnings): remove or annotate unused parameters, functions and variables
- init_command, s3_signer test, request_handler_lifetime test: comment out
the unused parameter name.
- video_content_handler: path is only read under YAMS_HAVE_FFPROBE.
- vector_memory_scaling_bench: main() takes no arguments.
- daemon_status_render: delete unused neutralText helper.
- DaemonMetrics: mallocStackLoggingNoCompactEnabled is only called in the
__APPLE__ block, so define it there.
- SocketServer: einval_streak only matters in the __APPLE__ EINVAL path.
- onnx_plugin_harness test, vector_backend_engine_compare bench,
work_coordinator test: mark platform-conditional or busy-loop
variables [[maybe_unused]].
Signed-off-by: trvon <git@trevon.dev>
* chore(warnings): fix sign-compare, range-loop, nodiscard and dangling-ref in tests
- search_admission_controller: count started workers in std::uint32_t so
the comparison with the uint32 cap is same-signed.
- p2p_manager: iterate the invalid-host list by const reference.
- integrity_verifier: discard the nodiscard results the tests do not
inspect with static_cast<void>.
- post_ingest_queue: findNode/findEdge take std::string_view so no
temporary std::string is created for the call (GCC
-Wdangling-reference false positive on the returned reference).
- topology_ablation_bench: the doc comment ended a line with a backslash,
which continues the comment (-Wcomment); show the env export on its own
line.
Signed-off-by: trvon <git@trevon.dev>
* chore(warnings): drop redundant std::move of a const captured json
The coroutine lambda is not mutable, so the captured optional<json> is
const and std::move(*progressToken) already selected the copy assignment.
Drop the std::move so the code states what actually happens.
Signed-off-by: trvon <git@trevon.dev>
* chore(warnings): mark __int128 use in db_integrity_stamp as an extension
-Wpedantic flags __int128. Use a __extension__ typedef, the GCC/Clang
idiom for an intentional extension, instead of the bare keyword.
Signed-off-by: trvon <git@trevon.dev>
* chore(warnings): remove always-true unsigned >= 0 comparisons
GCC -Wtype-limits flagged 51 test assertions of the form
CHECK(unsignedValue >= 0) that can never fail, plus a dead
`totalCount.value() < 0` clause in the graph listByType handler (the
count is std::size_t). In the tests keep the evaluation as a
static_cast<void> so the accessors are still exercised; in the handler
drop the dead clause and keep the range check.
Signed-off-by: trvon <me@trevon.dev>
---------
Signed-off-by: trvon <me@trevon.dev>
Signed-off-by: trvon <git@trevon.dev>
121 lines
3.6 KiB
C++
121 lines
3.6 KiB
C++
#include <algorithm>
|
|
#include <chrono>
|
|
#include <cmath>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <random>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include <yams/vector/sqlite_vec_backend.h>
|
|
|
|
using namespace yams::vector;
|
|
|
|
namespace {
|
|
|
|
struct Config {
|
|
size_t dim = 128;
|
|
size_t vectors = 1000;
|
|
unsigned seed = 42;
|
|
};
|
|
|
|
std::vector<float> makeRandomVec(size_t dim, std::mt19937& rng) {
|
|
std::uniform_real_distribution<float> dist(-1.0f, 1.0f);
|
|
std::vector<float> v(dim);
|
|
for (auto& x : v)
|
|
x = dist(rng);
|
|
return v;
|
|
}
|
|
|
|
void bench(const char* engineLabel, VectorSearchEngine engine, const Config& cfg) {
|
|
std::mt19937 rng(cfg.seed);
|
|
|
|
SqliteVecBackend::Config beCfg;
|
|
beCfg.embedding_dim = cfg.dim;
|
|
beCfg.search_engine = engine;
|
|
SqliteVecBackend backend(beCfg);
|
|
auto init = backend.initialize(":memory:");
|
|
if (!init) {
|
|
std::printf("%-14s d=%zu n=%zu ERROR: %s\n", engineLabel, cfg.dim, cfg.vectors,
|
|
init.error().message.c_str());
|
|
return;
|
|
}
|
|
auto create = backend.createTables(cfg.dim);
|
|
if (!create) {
|
|
std::printf("%-14s d=%zu n=%zu ERROR: %s\n", engineLabel, cfg.dim, cfg.vectors,
|
|
create.error().message.c_str());
|
|
return;
|
|
}
|
|
|
|
std::vector<VectorRecord> records;
|
|
records.reserve(cfg.vectors);
|
|
for (size_t i = 0; i < cfg.vectors; ++i) {
|
|
VectorRecord rec;
|
|
rec.chunk_id = "chunk_" + std::to_string(i);
|
|
rec.document_hash = "doc_" + std::to_string(i / 4);
|
|
rec.embedding = makeRandomVec(cfg.dim, rng);
|
|
rec.content = "benchmark content " + std::to_string(i);
|
|
records.push_back(std::move(rec));
|
|
}
|
|
|
|
auto t0 = std::chrono::steady_clock::now();
|
|
auto insert = backend.insertVectorsBatch(records);
|
|
if (!insert) {
|
|
std::printf("%-14s d=%zu n=%zu INSERT ERROR\n", engineLabel, cfg.dim, cfg.vectors);
|
|
return;
|
|
}
|
|
|
|
auto build = backend.buildIndex();
|
|
if (!build) {
|
|
std::printf("%-14s d=%zu n=%zu BUILD ERROR\n", engineLabel, cfg.dim, cfg.vectors);
|
|
return;
|
|
}
|
|
auto t1 = std::chrono::steady_clock::now();
|
|
|
|
// Run a few queries to get steady-state latency
|
|
std::vector<float> query = makeRandomVec(cfg.dim, rng);
|
|
const int queryCount = 20;
|
|
double totalUs = 0;
|
|
for (int q = 0; q < queryCount; ++q) {
|
|
auto qs = std::chrono::steady_clock::now();
|
|
auto result = backend.searchSimilar(query, 10, 0.0f);
|
|
auto qe = std::chrono::steady_clock::now();
|
|
if (!result)
|
|
continue;
|
|
totalUs += std::chrono::duration<double, std::micro>(qe - qs).count();
|
|
}
|
|
double meanUs = totalUs / queryCount;
|
|
|
|
double buildMs = std::chrono::duration<double, std::milli>(t1 - t0).count();
|
|
|
|
std::printf("%-14s d=%-4zu n=%-6zu build=%8.1f ms query=%8.1f us\n", engineLabel, cfg.dim,
|
|
cfg.vectors, buildMs, meanUs);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
int main() {
|
|
std::printf("%-14s %-5s %-7s %-12s %-12s\n", "engine", "dim", "vectors", "build_ms",
|
|
"query_us");
|
|
std::printf("%s\n", std::string(56, '-').c_str());
|
|
|
|
// Sweep dims at a fixed corpus size
|
|
for (size_t dim : {128ul, 384ul, 1024ul}) {
|
|
Config cfg;
|
|
cfg.dim = dim;
|
|
cfg.vectors = 2000;
|
|
bench("simeon-pq", VectorSearchEngine::SimeonPqAdc, cfg);
|
|
bench("vec0-l2", VectorSearchEngine::Vec0L2, cfg);
|
|
}
|
|
|
|
// Sweep corpus sizes at a fixed dim
|
|
for (size_t n : {500ul, 2000ul, 10000ul}) {
|
|
Config cfg;
|
|
cfg.dim = 384;
|
|
cfg.vectors = n;
|
|
bench("simeon-pq", VectorSearchEngine::SimeonPqAdc, cfg);
|
|
bench("vec0-l2", VectorSearchEngine::Vec0L2, cfg);
|
|
}
|
|
|
|
return 0;
|
|
}
|