Crucible LLM :: Bench your LLM and server. Is it fast enough… for everyone?

I built Crucible LLM — a terminal-based benchmarking suite that stress-tests any OpenAI-compatible inference server and measures what a real user actually experiences. One static Rust binary. No Python. No venv. No dependencies.

Why it exists

Most benchmarks shout “xx.x tokens/sec!” and stop. But when 32 users hit that server at once, each one gets 2 tokens/sec. A number that looks fast in the aggregate can feel painfully slow per user. Crucible measures that gap — the difference between a server’s peak throughput and what each individual connection actually gets — as well as how competent the LLM is at real tasks.

What it does

  • Single static binary — built in Rust, runs from any terminal on any box. No install, no runtime, no system libraries.
  • TUI-first — a 60 Hz interactive dashboard with real-time throughput graphs, live model discovery, and per-engine metrics.
  • Seven benchmark engines covering the full arc: speed → concurrency → long-context retrieval → reasoning → structured output → energy → flat-out max throughput.
  • The “practical sweet spot” — not just where aggregate throughput plateaus, but the maximum number of users where each one still gets a comfortable ≥ 30 tokens/sec.
  • Reasoning-model aware, done right — separates a model’s chain-of-thought from its actual answer, judges on the answer, and reports an over-thinker honestly instead of scoring it as a failure.
  • Deeper-context NIAH — drive your own retrieval matrix and probe RoPE/YaRN-extended windows well past 128k.
  • Multi-vendor GPU monitoring — auto-detects NVIDIA, AMD, or Intel. Live power, utilization, VRAM, temperature, and energy-per-token (Linux).
  • Any OpenAI-compatible server — vLLM, Ollama, llama.cpp, LM Studio, SGLang, Unsloth, TGI. Point it at a /v1 endpoint and go.
  • 3 visual themes — Cyberpunk, Vampire, or Monochrome Pastel. Pick on first run, change anytime.
  • Headless / CI-ready — pure-JSON output, meaningful exit codes, and export to JSON, Markdown, or CSV for automated regression pipelines.

See it in action

Live Monitor screenshot — real-time throughput graph with auto-scaling y-axis, engine-transition markers, and live event log.

Try it

Grab the latest pre-compiled binary from the Releases page:

chmod +x crucible-llm-v0.1.5-linux-x86_64
./crucible-llm-v0.1.5-linux-x86_64

Or build from source (requires a stable Rust toolchain):

git clone https://github.com/MadGoatHaz/crucible-llm
cd crucible-llm
cargo build --release
./target/release/crucible-llm

On first run, the TUI asks you to pick a theme, then walks you through entering your server URL and picking a model.


— Crucible LLM v0.1.5 — Reasoning, Done Right

A foundational one. The last release tried to suppress a reasoning model’s thinking to keep the capability tests fair — and it mostly worked, right up until you hit a server that ignores per-request suppression (which a lot of newer “config-only” inference servers do) or a Qwen that won’t honor /no_think. That silently turned capable models into fake failures. So 0.1.5 changes the philosophy.

Stop guessing The correctness guarantee is now the token budget — the one knob every server honors. A reasoning model gets enough room to finish its chain-of-thought and commit the answer (C1 default raised to 2048, C3 to 4096, both now tunable with --niah-max-tokens / --structured-max-tokens). Suppression is kept, but only as a best-effort speed optimization — fast where a server honors it, harmless where it drops the field. No more per-backend matrix.

Over-thinkers are reported, not failed. If a model spends its entire budget thinking and never answers, that’s now its own honest outcome — truncated_by_reasoning — shown as 74/77 pass, 3 truncated instead of counting them as capability failures. A wrong answer is still a fail; a no-answer-from-overthinking is its own category, surfaced in the terminal, --json, the database, and the TUI. (C2 is deliberately left alone — it needs the chain-of-thought and scores fine with it.)

Deeper context, your numbers. The needle-in-a-haystack engine is now fully yours to drive:

  • --niah-contexts 16k,64k,256k,1M and --niah-depths 0,25,50,75,100 — build your own retrieval matrix at runtime (no recompile).
  • --niah-custom 500k — a single-window “count test” for probing RoPE / YaRN-extended context and seeing exactly where your model’s recall falls off.
  • The haystack generator scales unbounded (a 1M-token document builds in milliseconds), and a size past the server’s limit degrades to a labeled per-cell error — never a crash, never a silent zero.
  • Sizes are honestly labeled (approx.) everywhere (log, TUI, JSON) unless you give it a --tokenizer for exact counts.

Cleaner transport. The client no longer guesses the stream type from the first byte — it routes on Content-Type, so servers that open a stream with :keep-alive comments (llama.cpp does) stream correctly instead of misrouting to the JSON path and poisoning the result.

Thanks

Two people drove a lot of this. @harshithmohan — five precise issues, plus a sharp follow-up on exactly why per-request suppression can’t be trusted — is what pushed the design to this point. And @strawberry — whose needle-in-a-haystack and pre-fill observations started the whole “make the numbers true” effort in the first place. Thank you both for the time and the rigor; this release is a direct result of your feedback.

:warning: Would love eyes on it

If you’re running a reasoning model — vLLM, llama.cpp, Ollama, LM Studio, SGLang, TGI — grab 0.1.5 and tell me:

  • Do NIAH / Reasoning / Structured look right for your model now?
  • Are you seeing any truncated_by_reasoning cases, and does that read honestly?
  • Trying a RoPE/YaRN build? What does --niah-custom show at the edge of your context window?

Post your numbers and what you’re running. Issues and war stories especially welcome.


Changelog

Version Date Highlights
0.1.5 2026-10-12 Reasoning, done right: hybrid design (token budget = correctness guarantee, best-effort suppression, truncated_by_reasoning over-thinker outcome, content-only scoring, C2 untouched), configurable C1/C3 budgets (defaults 2048/4096 via --niah-max-tokens/--structured-max-tokens), --no-disable-thinking, NIAH runtime ladders + --niah-custom high-context (RoPE/YaRN) + unbounded 1M+ haystack, (approx.) token-honesty across log/TUI/JSON, SSE Content-Type routing fix.
0.1.4 2026-10-11 Measurement integrity: reasoning-aware NIAH/Reasoning/Structured, pre-fill split into TTFT latency + long-prompt throughput, per-user vs. capacity dual denominators, canonical MTP ratio, all 7 engines selectable, full run traceability, 100 ms-trace energy, real json_schema constrained decoding.
0.1.3 2026-10-05 GPU & Power Monitor (View 4): multi-GPU table, power-over-time graph, system power, idle baseline, energy + $/1M token cost, efficiency metrics
0.1.2 2026-10-04 Multi-vendor GPU monitoring (NVIDIA/AMD/Intel), auto-detection, NVIDIA on by default, J/token
0.1.1 2026-10-03 3 themes, Flat Out engine, accurate token counting, 30 t/s sweet spot, methodology transparency, history view
0.1.0 2026-10-01 Initial release: 6 engines, TUI, headless CLI, SQLite history, export, concurrency sweep

Contribute

:backhand_index_pointing_right: github.com/MadGoatHaz/crucible-llm — star the repo, open an issue, or fork and contribute.

Feedback: If you’re running any of these backends, hit me up with your numbers — especially on 0.1.5 with a reasoning model. I want to know if the sweet spot, Flat Out, and the new truncated_by_reasoning / deep-context results match what you’re seeing. Issues, PRs, and war stories all welcome.

2 Likes

You might pull some ideas from GitHub - local-inference-lab/llm-inference-bench: LLM inference decode throughput benchmark with Rich TUI dashboard. Measures token generation speed across concurrency levels and context lengths. Supports SGLang and vLLM engines. · GitHub this is the blackwell performance community gold standard right now

1 Like

Very interesting, similar in many ways. Thanks for the heads up. It’s good to know what people are using.

Although I think Crucible aims to and offers more insight into not just the performance overall, but the LLM itself as well.

Thanks again :+1:

Am I missing something? I downloaded it, entered the URL, chose a model, hit enter, the model loaded on the target, but it’s not running any tests. I am using llama.cpp but according to the quick little readme here, it shouldn’t matter. I tried this, pointing it at several different machines I have. I also just tried pointing it directly at LM Studio and it seems to behave the same. A tiny blip in the GPU usage and then nothing.

I was looking forward to really pushing some tokens and running some benchmarks. I actually have a project I’m working on right now to figure out what the best model/quant is for use on my rig with Qwen 3.8 Flash Next, and this would be conveniently, immediately, ironically useful.

1 Like

You are correct in what you’re seeing and I can confirm I’ve replicated it on my side - it is for sure a deadlock and i’m working on a change to the engines now. I should have a the new release with a couple new merges as well released here within the hour or so. Thanks for the feedback! - I’ll update the main thread and this post when they’re up.

1 Like

The idea of measuring per-user performance instead of only aggregate tokens/sec is really useful. I especially like the “practical sweet spot” concept, because a server can look great in a benchmark while individual users are already getting poor response times. The TUI and CI/JSON output also make it seem practical for both testing and ongoing monitoring.

1 Like

I’m sitting here hitting F5 every hour on the Github page watching the commits roll in like :eyes:. I know it’s a volunteer project, but I’m very excited.

1 Like

I’m so sorry, I fell asleep at the desk last night and today was a nightmare - BUT, I’m wrapping up the release right now… I won’t give a time frame as I blew it last time saying that … Soon, very very soon (tonight). I will update here when It’s pushed. LOTS of changes I wanted to complete that all got included in this release.

Crucible LLM v0.1.1 — Big Update - Pushed and should be up. Any and all feedback VERY welcome. THANKS!

1 Like

I’m glad I upgraded the power supply recently…

Crucible LLM v0.1.2 — GPU Monitoring for Everyone - Pushed Again: Any and all feedback VERY welcome. THANKS!

If you could - I would love to know how Crucible reports the power for your AMD cards. I don’t have any AMD cards to test on (nor Intel for that matter atm).

It reports only the first card? This feature is very new. I can say, what it’s reporting is definitely correct. The 9700 spikes over 400 watts on NIAH test because it’s pure prefill. I was monitoring with LACT and running the benchmarks from my dedicated Linux desktop remotely. It only sees one card, other than that this is VERY nice.

1 Like

– That is INCREDIBLY helpful. Thank you. I was wondering if it was going to only grab one card, this confirms that - Also, are you using 0.1.3? - I have been working on adding a new power tab this evening - I wonder if the cards are reported in the power tab or if it’s still pulling GPU0?

Thanks a million either way!

I just downloaded a fresh copy of it because as mentioned in the notes, it needs to run on the machine with the cards in it in order for that feature to work. And I noticed that it’s on 0.1.3 versus the 0.1.1 I’ve been using all day. Only one GPU shows up on the Power tab, but all of the metrics appear to be correct, which is very promising.

I’m also wondering how it calculates the cost per million tokens. Is there a way to provide a power cost? That figure does appear to be a little high… It also appears to be incrementing, like it’s supposed to be a flat figure. Unless it only says dollar per million tokens and it actually means cost for this session? There’s also the difference of input versus output tokens… Anyway, I really like what you’ve been doing with this thing. Keep it up. This is so fantastic. This is already incredibly useful. As I mentioned before, I’ve been using this all day to benchmark different models to figure out which ones can properly locate data in their context, which ones are the most effective for the use cases that I’m going to be subjecting them to… I have a pile of hardware lying around and most of these are doing double duty, like the 5090 in my daily driver, and so on. Being able to just point an executable at an API endpoint and have it return a report that says, this loaded configuration can do X, Y, and Z, and it can’t do A, B, and C is so incredibly helpful.

I’m also curious about the needle in a haystack test. So far, not a single model that I’ve loaded has been able to return anything at all on any position in the 128K context. I also would like to be able to test beyond that because I’ve been using Qwen with the maximum context set, and I’d like to see how it does with rope/yarn.

1 Like

— Crucible LLM v0.1.3 — GPU & Power Monitor Released

Lots of changes and polishing - Thank you @Strawberry for the feedback and testing!

Thank you for sharing your tool.

May you consider for this aspect a dispersion behaviour, either in tk/s or more praticaly in latency ?

This is a really good idea! - Can you elaborate on what you’d like to see / how you could benefit from such information? It would help me design / configure the data to be the most helpful to the end user.

Thank for the feedback / suggestions!

With 4x9700?

I am in fact using 4x 9700 pro cards. Mostly qwen 3.8 flash next, qwen 3.8 27b models and their derivatives. I recently switched to Radiance which is a real game changer for these cards.

Hey, so I have one more question / suggestion / discussion item. I asked some colleagues to run the needle in a haystack check on their models as a sanity check on mine. They were getting some very interesting results and it was failing almost 100% of the time no matter what their settings were. So, they had their models go digging around in the codebase, which I’ll admit I probably should have done myself, but didn’t.

To run the needle in a haystack check, do you have to disable thinking? It looks like it caps the output tokens at 64. Which means if you have a thinky model, the thinking will run out the cap and it will fail the test, even if the return would have been perfect otherwise. If this really is the case, it would go quite a long way to explaining the oddness I’ve noticed.

They also had some comments about the prompt that’s being used in A and F. It’s only 45 tokens, so the reported speed for the pre-fill is entirely inaccurate and doesn’t scale.

If I get any other feedback, I’ll be sure to share it here. And of course, as this is a volunteer project, you have no obligation to go fix it, but I thought you might want to know.

1 Like