Skip to content

perf: reduce peak RAM via BlockStorage enum, flood fill bitmap, and ground generation optimization#747

Merged
louis-e merged 6 commits intomainfrom
memory-optimization-blockstorage-floodfill
Feb 9, 2026
Merged

perf: reduce peak RAM via BlockStorage enum, flood fill bitmap, and ground generation optimization#747
louis-e merged 6 commits intomainfrom
memory-optimization-blockstorage-floodfill

Conversation

@louis-e
Copy link
Owner

@louis-e louis-e commented Feb 9, 2026

Memory Optimization: BlockStorage + FloodBitmap + Ground Generation

Summary

Reduces peak RAM usage by an estimated 300–800 MB (depending on world size and --fillground), with no increase in generation time (most paths are faster).

Changes

1. BlockStorage enum (common.rs)

Replace inline [Block; 4096] section arrays with a two-variant enum:

  • Uniform(Block) — 1 byte for homogeneous sections (AIR, STONE, etc.)
  • Full(Vec<Block>) — heap-allocated for mixed sections (small inline footprint in HashMap)

Sections that are entirely AIR (above buildings) or entirely STONE (--fillground) now cost 1 byte instead of 4,096.

2. compact_sections() before save (mod.rs)

Scans all sections before serialization and collapses any Full(Vec) that became uniform back to Uniform, freeing ~4 KiB each. Particularly impactful for --fillground.

3. FloodBitmap replaces HashSet (floodfill.rs)

Replaced HashSet<(i32, i32)> (visited set) with a compact bitmap using 1 bit per coordinate:

  • ~400× memory reduction: 48 MB → 122 KB for a 1000×1000 polygon
  • Faster: bit operations vs. hashing

4. set_block_if_absent() (common.rs, mod.rs)

Single-pass method that resolves region→chunk→section once and only writes if AIR. Eliminates double HashMap traversal (get_block + set_block) in ground generation.

5. fill_column() for underground fill (common.rs, mod.rs, data_processing.rs)

Fills an entire vertical column with one region/chunk lookup instead of per-Y-level. ~6× fewer HashMap lookups for --fillground.

6. Bedrock serializer updated (bedrock.rs)

section.blocks[idx]section.get_block_at_index(idx) to match the new BlockStorage API.

Testing

  • All 43 tests pass
  • Zero warnings
  • No behavioral changes — purely internal optimization

…round generation optimization

- Replace inline [Block; 4096] section arrays with BlockStorage enum:
  Uniform(Block) for homogeneous sections (1 byte vs 4 KiB),
  Full(Vec<Block>) for mixed sections (heap-allocated, small inline footprint).
  Saves ~200-500 MB for typical worlds.

- Call compact_sections() before save to collapse Full sections that
  became uniform (e.g. all-STONE from --fillground) back to Uniform.

- Replace HashSet<(i32,i32)> in flood fill with FloodBitmap (1 bit per coord).
  ~400x memory reduction: e.g. 48 MB -> 122 KB for 1000x1000 polygon.

- Add set_block_if_absent() to avoid double HashMap traversal in
  ground generation (get_block + set_block -> single pass).

- Add fill_column() for efficient underground fill: resolves region/chunk
  once per column instead of per Y-level (~6x fewer HashMap lookups).

- Wire optimized methods into ground generation loop in data_processing.rs.
Copilot AI review requested due to automatic review settings February 9, 2026 17:59
@github-actions
Copy link

github-actions bot commented Feb 9, 2026

⏱️ Benchmark run finished in 0m 31s
🧠 Peak memory usage: 948 MB

📈 Compared against baseline: 30s
🧮 Delta: 1s
🔢 Commit: fae533f

🟢 Generation time is unchanged.

📅 Last benchmark: 2026-02-09 18:02:55 UTC

You can retrigger the benchmark by commenting retrigger-benchmark.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR focuses on reducing peak memory usage during world generation by changing how modified Minecraft chunk sections and flood-fill visited sets are stored, and by optimizing hot-path block placement for ground generation.

Changes:

  • Introduces BlockStorage (Uniform vs Full(Vec<Block>)) for section block storage and compacts sections before saving.
  • Replaces flood fill HashSet visited tracking with a 1-bit-per-cell bitmap.
  • Optimizes ground generation by adding “write only if AIR” and “fill vertical column” APIs to reduce repeated map lookups.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/world_editor/mod.rs Adds column/absent-write helpers and compacts sections before serialization.
src/world_editor/common.rs Implements BlockStorage, new fast-path write helpers, and section compaction logic.
src/world_editor/bedrock.rs Updates Bedrock serialization to read blocks via the new storage API.
src/floodfill.rs Implements FloodBitmap to track visited cells with a compact bitmap.
src/data_processing.rs Updates ground generation to use the new faster write/fill APIs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Change 'three cases' to 'two cases' in BlockStorage doc comment
  (only Uniform and Full variants exist)
- Clear stale properties via properties.remove(&idx) in
  set_block_if_absent() and fill_column() after writing a block,
  so leftover NBT metadata from a previous block does not persist
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…ord doc comment

- to_section() Uniform fast path now gated on self.properties.is_empty()
  so per-index properties are never silently dropped
- Remove compact_sections() eprintln! that polluted stderr in normal operation
- Reword set_block_if_absent_absolute doc to clarify it checks the
  in-memory overlay, not the on-disk world
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Delete fill_blocks_absolute (zero call sites, was lint-suppressed)
- Simplify compact_sections by removing the dead counter
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

set_block now removes any leftover per-index properties, matching
the behaviour of set_block_with_properties and preventing stale
NBT data from leaking into serialization or blocking compaction.
@louis-e louis-e requested a review from Copilot February 9, 2026 18:50
@louis-e louis-e merged commit ea9f11d into main Feb 9, 2026
6 of 8 checks passed
@louis-e louis-e deleted the memory-optimization-blockstorage-floodfill branch February 9, 2026 19:16
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.

2 participants