Commit Graph
15 Commits
Author SHA1 Message Date
popertots 50788af3c7 feat(optimization): implement data-oriented chunk architecture
Phase 1: Bit-packed standability
- Add ChunkData struct with 4 bitsets per chunk (stand_in/on for floor/fixture)
- Replace 4 HashMap lookups per standability check with O(1) bit operations
- Memory: ~2KB bitsets per chunk vs ~50KB HashMap overhead

Phase 2: Reactive connectivity
- Add dirty_chunks HashSet to ChunkMap for incremental updates
- update_chunk_connectivity now O(d) where d = dirty chunks
- Early exit when no changes, preventing O(N) full rebuilds

Phase 3: Async terrain baking
- Move terrain generation to AsyncComputeTaskPool
- spawn_terrain_tasks: non-blocking task spawn (~34µs)
- apply_terrain_blobs: batched entity spawn on main thread
- Eliminates main-thread stutters during world generation
2026-03-19 17:01:51 +00:00
popertots a5154f73dd docs(pathfinding): add documentation and remove unused async infrastructure
- Add comprehensive module documentation explaining tier architecture
- Add TileMap documentation explaining design choices (FxHashMap, packed data)
- Remove unused async pathfinding code (StandableTileSnapshot, spawn_async_path_task)
- Remove unused imports (check_ready, rayon, StdHashMap)
- Fix unused variable warnings with underscore prefixes
- Add #[allow(dead_code)] for intentionally unused fields
2026-03-18 22:08:27 +00:00
popertots 00cbd92491 refactor: simplify to time-sliced synchronous path queue
The async pathfinding with StandableBitGrid caused massive lag due to synchronous
bounding box calculation in the main thread (millions of hashmap lookups for long paths).
Additionally, the splicing logic had a catastrophic bug where it applied a single
finished path to ALL entities unconditionally.

Solution:
- Revert to thread-local synchronous A*
- Implement PathRequestQueue to process max 8 paths per frame
- Keep provisional paths for immediate movement
- Since entity walks provisional path, full path calculates from current position,
  eliminating the need for complex splicing logic.
2026-03-18 17:23:48 +00:00
popertots c902cff908 feat: async pathfinding with provisional paths and bit-grid snapshots
- Add StandableBitGrid: O(1) bit-packed snapshot (~6KB per 50k tiles vs HashMap overhead)
- Implement two-tier pathfinding: sync for short paths (<64 tiles), provisional+async for long paths
- calculate_provisional_path: capped A* returning path to best heuristic node
- calculate_async_path: A* using bit-grid (Send+Sync, no thread_local)
- prepare_paths system: dispatches provisional paths immediately, spawns async for full paths
- poll_async_paths + splice_completed_async_paths: seamless path transition when async completes
- Entities start walking immediately on provisional path while full path computes in background

Architecture:
  FixedUpdate: prepare_paths → update_wandering_targets → movement
  PostUpdate: poll_async_paths → splice_completed_async_paths

Priority: DF-like pathing (immediate movement) > performance > memory
2026-03-18 16:35:39 +00:00
popertots 367ab26d5e Fix performance regressions: remove TIER0, consolidate scratchpads, remove Arc trap
Key fixes based on benchmark analysis:
1. Remove TIER0 Vec-based pathfinding - O(N) linear scan was slower than FxHashMap for typical path lengths
2. Consolidate scratchpads into single AStarScratchpad struct - eliminates nested RefCell borrow overhead
3. Remove Arc wrapper from TileMap - eliminated Copy-on-Write trap causing 63ms stutters
4. Replace AHashMap with FxHashMap - FxHash is faster for small integer keys like IVec3
5. Simplify tier logic - single pathfinding function with scratchpad reuse

Benchmark analysis showed:
- Original: 1.95 µs/node, P99 1.1ms, Max 5ms
- TIER0/TIER1 regression: 2.89 µs/node (+48%), P99 5ms (+348%)
- Root causes: Vec linear scan in TIER0, nested RefCell borrows, Arc::make_mut CoW

This should restore and improve performance by using simple FxHashMap scratchpad for all paths.
2026-03-18 15:30:48 +00:00
popertots 466a20700a Wrap TileMap HashMaps in Arc for async pathfinding access
- Add Arc<AHashMap> wrapper around floor_tiles, fixture_tiles, item_tiles
- Copy-on-write semantics: Arc::make_mut clones only if other Arcs exist
- Add insert_floor, insert_fixture, insert_item, remove_item methods
- Add get_floor_mut, get_fixture_mut for visibility updates
- Update all mutation sites to use new TileMap methods
- Enables cheap Arc::clone for async pathfinding workers
- Single-threaded pathfinding: no clone, direct access
- Multi-threaded pathfinding: clone Arc, read without locks
2026-03-18 14:56:57 +00:00
popertots 8478b385bc Optimize TileMap: replace HashMap with AHashMap, pack tile data
- Replace std HashMap (SipHash) with ahash::AHashMap for fast non-crypto hashing
- Pack tile data from tuples to structs: FloorTileData (~35 bytes) and FixtureTileData (~18 bytes)
- FloorTileData: pack 3 bools into single flags byte, use u8 for id/weight
- FixtureTileData: pack 2 bools into single flags byte
- Update all accessors: is_standable_tile, visibility, terrain generation, forestry
- Preparation for async pathfinding (Arc wrapping to come in follow-up)

Memory reduction: ~54% for floor tiles (76→35 bytes), ~62% for fixtures (48→18 bytes)
Hash performance: AHashMap uses fxhash, faster than SipHash for game data
2026-03-18 14:52:46 +00:00
popertots aeef78eca2 Fix tiled patching 2026-03-18 09:22:47 +00:00
popertots b0b0ca0390 optimize visibility calcs 2026-02-28 11:27:50 +00:00
popertots b1de9f95c2 quilted chunk optimisations 2026-02-28 00:07:07 +00:00
popertots 4ef68c4e04 migratetion to 0.18.0 2026-02-16 00:02:00 +00:00
popertots 886d162963 dropped item rotation 2026-02-15 18:56:38 +00:00
popertots 975ac20876 minor 2025-09-14 19:04:34 +01:00
popertots 4c4c985be3 item flashing 2025-09-14 18:48:50 +01:00
popertots ee7ac39ad5 refactor file locations for readability 2025-09-11 18:23:53 +01:00