Use an opaque int64_t handle for correlating async responses instead of raw pointers. HTTP uses sequence_id as the handle and stores response data in a unique_ptr<HttpResponseContext> keyed by sequence_id.
Closes#5
Adds a Gitea Actions workflow that runs pre-commit checks and builds/tests the project on clang and gcc for both amd64 and arm64.
weaseljson is checked out, built, and installed locally because weaseldb depends on it via `find_package(weaseljson REQUIRED)`.
Also switches the llhttp FetchContent declaration from a tarball URL to a git repository pinned to the same release commit. The tarball redirect goes through codeload.github.com, which can be blocked in restricted network environments; using git keeps the fetch on github.com.
Reviewed-on: #6
Co-authored-by: Weaselbot <weaselbot@weaselab.dev>
Co-committed-by: Weaselbot <weaselbot@weaselab.dev>
Adds `reproduce_threading_report.sh` to run the WeaselDB server and
load tester configuration described in `threading_performance_report.md`.
Improvements over the original draft:
- Validates the build directory, config file, and required binaries
before starting, and expects to be run from the project root.
- Wraps server shutdown and log printing in an EXIT/INT/TERM trap
so the server is always cleaned up, even if the script is
interrupted or the load tester fails.
- Makes the `ulimit -n` increase best-effort instead of fatal.
- Uses the existing `DURATION` variable consistently in the load
tester invocation.
- Adds a final check that the unix socket was created before
launching the load tester.
- Uses 2 connect threads on the client, which is sufficient for
establishing 2000 connections over the 30-second run.
The previous report claimed 1.0M req/s at 740ns serial CPU work for the /ok health check endpoint. That measurement was made with an earlier design that transferred unique ownership of connections through the pipeline.
The current server-owned connection model adds per-request synchronization overhead (mutex + WeakRef + pending response queue) that lowers the raw /ok throughput. Reproducing on an AMD Ryzen 9 7900 with the current Release build gives approximately 825k sustained req/s with the same 740ns serial CPU work.
Updated the report to reflect the reproduced numbers and added a note explaining the historical context and why the ownership model changed (to support streaming endpoints like /v1/subscribe and safer async responses).
The GNU assembler expects `.size symbol, .-symbol`. The previous
`.size spend_cpu_cycles, spend_cpu_cycles` expression is not a constant
and breaks compilation on AArch64 Linux. Use the correct form so the
project builds on ARM64.
Replace the scalar ARM fallback in update_histogram_buckets with a NEON
implementation that processes two buckets per iteration, matching the
existing AVX path. The wrapper now dispatches to the SIMD path on both
x86-64 and AArch64 and falls back to scalar code on other architectures.
The metrics histogram update code unconditionally included <immintrin.h>
and used __attribute__((target("avx"))) SSE/AVX intrinsics, which only
exist on x86-64. This prevented the project from compiling on ARM64.
Guard the x86-64 SIMD implementation and the <immintrin.h> include with
an architecture check, and add a portable scalar fallback for non-x86-64
platforms (e.g., ARM64). A thin wrapper function keeps the call sites
unchanged and preserves the AVX fast path on x86-64.
Closes#3