Performance¶
Civillis evaluates millions of blocks per spawn attempt while keeping each check at near-constant time. This page explains the optimization strategy and its real-world cost profile.
The Core Challenge¶
Every time a hostile mob tries to spawn naturally, the engine must answer: "How civilized is this location?" This requires aggregating block data across a configurable detection area (default 240×240×48 blocks = 675 voxel chunks). Doing this naively on every spawn attempt would be catastrophically expensive.
The solution is a shard-based caching engine built on three pillars:
- Pre-aggregated results — The 675-chunk aggregation is computed once and cached. Subsequent spawn checks are a single map lookup: O(1), ~50 ns.
- Delta propagation — When blocks change, only the affected shard is recomputed and the difference is applied to cached results. No full re-aggregation ever runs after the initial computation.
- Palette pre-filtering — Before scanning 4,096 blocks in a chunk section, the engine checks Minecraft's internal block palette for recognized civilization blocks. Sections with no targets are skipped in ~1 μs instead of a ~100 μs full scan — in wilderness this eliminates virtually 100% of scanning work.
Civilization Scoring Engine¶
The following diagram shows the full data flow through the scoring engine — the component responsible for the O(1) spawn checks. All key paths (spawn checks, block changes, cold loading, prefetching, TTL eviction) are shown with their typical costs.
flowchart TD
SpawnCheck(["Spawn Check"])
BlockChange(["Block Change"])
SpawnCheck ~~~ BlockChange
Miss{{"cache miss<br/>aggregate from L1<br/>~34 μs"}}
Hit{{"cache hit<br/>~50 ns"}}
Delta{{"recompute +<br/>propagate delta<br/>~13 μs"}}
L1[("L1 Shards<br/>per-chunk scores")]
Result[("Result Shards<br/>pre-aggregated")]
SpawnCheck --> Miss --> L1
SpawnCheck --> Hit --> Result
BlockChange --> Delta --> Result
L1 -->|"distance-weighted aggregate"| Result
Prefetch{{"prefetch nearby<br/>~0.9 ms/s"}}
Presence{{"decay recovery<br/>~10 μs/s"}}
ColdLoad{{"cold read<br/>~0.1 ms"}}
H2[("H2 Cold Store<br/>async I/O")]
PlayerMove(["Player Move (1/s)"])
PlayerMove --> Prefetch --> L1
PlayerMove --> Presence --> Result
H2 --> ColdLoad --> L1
L1 -->|"TTL 5 min evict"| H2
Result -->|"TTL 60 min evict"| H2
Cost Summary¶
| Operation | Typical cost | Frequency |
|---|---|---|
| Spawn check (warm) | ~50 ns | Every natural spawn attempt |
| Spawn check (cold) | ~34 μs | First spawn in a new area |
| L1 compute (palette skip) | ~1 μs | Most chunk sections |
| L1 compute (full scan) | ~100 μs | Sections with civilization blocks |
| Block change + delta | ~13 μs | Every block placement/removal |
| Database cold read | ~0.1 ms | L1 evicted from memory |
| Prefetch per player (moved) | ~0.9 ms/s | Once per second when player moves |
| Prefetch per player (stationary) | ~0.01 ms/s | Once per second (presence only) |
The scoring engine alone scales comfortably to hundreds of players. The real cost story, however, depends on what happens around it.
Mob Flee AI Performance Notes¶
Mob Flee AI is a behavior-layer system and is intentionally decoupled from the O(1) civilization score query path.
- It does not change the cache topology (L1/Result shards) or delta propagation math
- It runs on periodic evaluations per mob (interval + jitter), not every tick for every mob
- Its practical cost scales with active hostile mob count and configured flee cadence
If a server needs stricter performance limits, mobFlee.enabled=false fully disables this behavior without affecting spawn suppression, decay, or head attraction.
Runtime Cost Profile¶
At runtime, the core paths are all stable:
- Civilization score query is O(1) on warm cache (map lookup)
- Block change update stays constant-time at shard level (recompute + delta propagation)
- Monster head checks are handled by spatial indexing, so typical overhead remains low
This means Civillis has no obvious performance hotspot in normal deployments. The dominant variable is still spawn-attempt volume (mob-cap churn), not one specific subsystem.
What Drives Cost on Live Servers¶
- Spawn churn: dark civilized areas can increase retry volume when mob cap fills slowly
- Player movement: prefetch and cache maintenance scale with active movement
- Extreme local head density: only when many enabled heads are packed into one active area
Multiplayer Server Budget¶
The table below gives a compact planning view for common server sizes.
| Server stage | Typical active pattern | Prefetch + presence | Spawn pipeline | Total Civillis cost | Tick budget used |
|---|---|---|---|---|---|
| Small (~10 players) | 3 explorers + 7 builders in lit bases | ~0.14 ms/tick | ~0.12 ms/tick | ~0.26 ms/tick | ~0.5% |
| Medium (~50 players) | 10 explorers + 40 builders across multiple bases | ~0.49 ms/tick | ~0.75 ms/tick | ~1.24 ms/tick | ~2.5% |
| Large (~100 players) | 20 explorers + 80 builders, mixed lighting quality | ~0.98 ms/tick | ~2.60 ms/tick | ~3.58 ms/tick | ~7.2% |
All values are rounded estimates under the stated assumptions; total cost is the sum of the two component columns in each row.
Observed upside in very large modpacks
In some heavy modpack environments, Civillis can improve overall server performance instead of only adding overhead. Real user feedback confirms this in Minecraft 1.20.1 Forge with 300+ mods: by reducing hostile mob pressure near established bases, total active-entity load and nearby AI churn can drop, which improves practical TPS stability. Treat this as an observed field result under specific pack conditions, not as a universal guarantee.
Edge case: very dense head hotspots
If many enabled heads are concentrated in one active attraction area, head-query overhead can become noticeable. Mitigation is straightforward: spread clusters, disable unused head types, or reduce attraction radius.