Skip to content

feat: MMO-scale world server with lazy zones, terrain, perf optimisations#65

Merged
Taure merged 3 commits intomainfrom
feat/mmo-scale-world
Apr 14, 2026
Merged

feat: MMO-scale world server with lazy zones, terrain, perf optimisations#65
Taure merged 3 commits intomainfrom
feat/mmo-scale-world

Conversation

@Taure
Copy link
Copy Markdown
Contributor

@Taure Taure commented Apr 13, 2026

Summary

Scales the world server to handle large tile-based MMOs (128K x 128K+ tiles, 500+ players per shard). Validated with a 5-minute benchmark of 500 real WebSocket players on a 2000x2000 zone grid: 6.4M messages, 9.88 GB of delta updates, zero failures.

Key additions

  • Lazy zone loading — on-demand zone spawn, idle reaping. 4M potential zones → only ~1000 alive at peak.
  • Terrain systemasobi_terrain encoding, asobi_terrain_provider behaviour, asobi_terrain_store cache. Serves 2-4KB compressed chunks on zone subscribe.
  • Spatial grid index — O(1) cell lookup for entity queries in dense zones.
  • Performance optimisations — broadcast batching (encode once, send to N), adaptive tick rates (hot/cold/empty), opt-in binary protocol (~25% bandwidth savings).
  • New callbacksterrain_provider/1, on_zone_loaded/2, on_zone_unloaded/2.

Benchmark results (500 players, 2000x2000 grid, 5 min)

  • 500/500 players connected with zero join errors
  • 17,850 msg/sec avg, 22,722 peak
  • 9.88 GB of real WebSocket traffic
  • Peak memory: 208 MB (single node)
  • Peak processes: 1,073 (out of 4M possible zones)
  • Connection time p99: 57ms under full load

Test plan

  • All 230 existing tests pass
  • 65+ new tests covering terrain, zone manager, spatial grid, broadcast batching, adaptive ticks, binary protocol
  • End-to-end integration test verifies terrain serving chain
  • Benchmark project at widgrensit/asobi_bench validates real WebSocket performance

Related

Taure added 3 commits April 12, 2026 19:59
Create the missing guide files that were referenced from README,
getting-started, configuration, and world-server docs. Both guides
point to asobi_lua (the standalone Lua runtime package) for full
documentation. Register guides in ex_doc extras config.
…isations

Scales the world server to handle large tile-based MMOs (128K x 128K+ tiles,
500+ players per shard).

## New modules

- `asobi_zone_manager` — lazy zone lifecycle with on-demand spawn and idle reaping
- `asobi_terrain` — pure functional chunk encode/decode/compress
- `asobi_terrain_provider` — behaviour for terrain data sources
- `asobi_terrain_store` — ETS cache with lazy loading and generate fallback
- `asobi_spatial_grid` — O(1) cell-based spatial index for entity queries
- `asobi_ws_binary` — opt-in binary WebSocket protocol (TLV format)

## Zone system changes

- Lazy zone loading with configurable idle timeout and max active zones
- Zones hibernate when empty, touch zone_manager on tick
- Zones serve terrain chunks on subscribe (one-shot, not per-tick)
- Zone manager uses ETS fast-path for hot lookups

## World server integration

- New optional behaviour callbacks: `terrain_provider/1`, `on_zone_loaded/2`, `on_zone_unloaded/2`
- Terrain store started automatically when game module provides a terrain_provider
- Zone manager wired into supervision tree

## Performance optimisations

- Broadcast batching: encode delta once, send pre-encoded binary to all subscribers
- Adaptive tick rates: hot zones (full rate), cold zones (reduced), empty zones (not ticked)
- Spatial grid: O(1) cell lookup replaces O(n) maps:fold
- Binary protocol: ~25% savings vs JSON+base64

## Config keys

- `lazy_zones` (auto-true when grid_size > 100)
- `zone_idle_timeout` (default 30000ms)
- `max_active_zones` (default 10000)
- `spatial_grid_cell_size` (opt-in spatial index)
- `cold_tick_divisor` (default 10)

## Tests

- 65+ new tests covering terrain, zone manager, spatial grid, broadcast batching,
  adaptive ticks, binary protocol, and end-to-end integration
- All 230 existing tests still pass

## Docs

- New guides: large-worlds.md, performance-tuning.md
- Updated world-server.md with link to large-worlds
- asobi_spatial:query_rect returns [{binary(), map()}], not 3-tuples
- Terrain serving block: bind unmatched return value
- terminate_zone result: explicitly ignore with _ =
@Taure Taure merged commit 9561935 into main Apr 14, 2026
15 checks passed
@Taure Taure deleted the feat/mmo-scale-world branch April 14, 2026 04:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant