§ 01.03Getting Started
Configuration
A Quicx daemon reads its entire runtime shape from a single quicx.conf file. Every number is exact — block counts, pool share, port — and is resolved before a byte of task traffic moves.
quicx.conf
# Quicx config — built-in default (no --config needed)
[server]
port = 16381
[allocator]
pool_size = 8388608
class = 16,2 # Connection — bounded by MAX_CONNECTIONS
class = 32,2 # Worker — bounded by MAX_CONNECTIONS
class = 48,1
class = 64,12 # Task — queue depth is uncapped, so this class IS the queue depth
class = 80,1
class = 96,1
# ... every other class up to 1024B keeps a 1% floor ...
# ... leftover percentage points are folded into the widest classes ...
class = 1008,1
class = 1024,1Default configuration
This is the built-in default as of v1.0.3. When you run
quicx start without a --config flag, the daemon uses these exact values — no file needed to get started: an 8 MiB pool split into all 64 exact-fit size classes from 16 bytes to 1024 bytes, in 16-byte steps.[server]
- port
- TCP port the daemon binds to. Producers and workers both dial the same port — routing is decided by the first message they send (
MSG_SUBMITvsMSG_READY). Default:16381.
[allocator]
The allocator block is parsed directly into the PMAD initializer. You own every byte of the pool — no hidden reserves, no growth. All arithmetic is performed at startup so the daemon either boots with the layout you asked for or refuses to start.
- pool_size
- Total bytes reserved via a single
mmapcall. Default is8388608(8 MiB), up from 1 MiB before v1.0.3. The allocator never grows past this number — if you exhaust it, newMSG_SUBMITframes are rejected withMSG_ERROR 0x01 (queue full). - class = SIZE,PCT
- Declares one size class: SIZE is the block size in bytes, PCT is the percentage of the pool that belongs to that class. Declare the classes in ascending SIZE order. The percentages must sum to
100; if they don’t, the daemon refuses to start. SIZE may not exceed1024bytes and at most64classes may be declared — both hard ceilings in the allocator as of v1.0.3.
Why the default split is weighted, not flat
A percentage buys bytes, not blocks — 1% of the 8 MiB default pool is 2,620 blocks at 16B but only 80 at 1024B. So the split isn’t even:
64B gets 12% (the Task class — queue depth is uncapped, so this class is the queue depth), 16B and 32B get 2% each (Connection and Worker, both bounded by MAX_CONNECTIONS), and every remaining class keeps a 1% floor — at 0% a class would be carved zero blocks and every allocation of that size would fail outright. Leftover percentage points are folded into the widest classes, which lifts the worst-off class the most. At the default 8 MiB pool, no payload class holds fewer than 124 blocks — all computed before the daemon accepts its first connection.Tuning rules of thumb
| Workload | Recommended shape | Why |
|---|---|---|
| Short JSON payloads (webhooks, emails) | 32, 64, 128 | Most MSG_SUBMIT frames land between 40–120 bytes; three tight classes eat the long tail with <5 % slack. |
| Mixed media (thumbnails, ML prompts) | 128, 512, 1024 | Wide spread within the 1024-byte ceiling — weight the biggest class heaviest. |
| Uniform binary blobs | one class at 100 % | Zero internal fragmentation. Highest throughput — see the PMAD benchmarks. |
Validation is strict on purpose
If
pool_sizeis not a multiple of every declared class size, if the percentages don’t sum to 100, if a class exceeds 1024 bytes, or if more than 64 classes are declared, the daemon exits with a precise error pointing at the offending line. This is deliberate — Quicx refuses to start in a “mostly-correct” state.