| name | rust-build-optimizer |
| description | Build Rust extensions efficiently in memory-constrained environments (2-4GB RAM), using optimized build profiles, split workspace compilation, and memory monitoring. Use when encountering OOM errors during Rust builds, setting up Rust backend in DevContainer/Colab, troubleshooting maturin failures, or optimizing compilation for low-memory systems. |
Rust Build Optimizer
Builds Rust extensions efficiently in memory-constrained environments, preventing OOM (Out of Memory) failures through optimized compilation strategies.
Quick Start
Pre-Flight Check
Verify available memory before building:
free -h
Optimized Build (Single Command)
uv run maturin develop
Expected:
- Build time: 3-5 minutes (dev profile)
- Peak memory: 1.0-1.5GB
- Success rate: 95%+ (vs frequent OOM without optimizations)
Split Workspace Build (For Severe Memory Constraints)
If standard build fails with OOM, use sequential workspace builds:
export CARGO_BUILD_JOBS=1
export CARGO_INCREMENTAL=1
export RUSTFLAGS="-C codegen-units=1"
cargo build --manifest-path rust/maou_io/Cargo.toml
cargo build --manifest-path rust/maou_index/Cargo.toml
cargo build --manifest-path rust/maou_rust/Cargo.toml
uv run maturin develop
Total time: ~11 minutes (vs 3-5min standard, but prevents OOM)
Peak memory per step: <1.5GB (vs 3.5GB for full workspace build)
Core Workflow
Standard Build Process
-
Environment Setup
cargo --version
rustc --version
echo $CARGO_BUILD_JOBS
echo $RUSTFLAGS
-
Monitor Memory During Build
time uv run maturin develop 2>&1 | tee build.log
watch -n 1 'free -h && ps aux --sort=-%mem | head -n 5'
-
Verify Successful Build
uv run python -c "from maou._rust.maou_io import hello; print(hello())"
ls -lh target/debug/lib_rust.so
Memory-Constrained Build Process (Detailed)
When standard build fails with OOM:
-
Check System Resources
free -h | grep Mem
swapon --show
df -h | grep /workspace
-
Clear Build Cache
cargo clean
rm -rf target/wheels/
du -sh target/
-
Run Split Workspace Build (Step-by-Step)
Step 1: Build maou_io (Arrow I/O library)
export CARGO_BUILD_JOBS=1
export CARGO_INCREMENTAL=1
export RUSTFLAGS="-C codegen-units=1"
cargo build --manifest-path rust/maou_io/Cargo.toml
echo "Step 1 complete: maou_io built"
Step 2: Build maou_index (Polars indexing)
cargo build --manifest-path rust/maou_index/Cargo.toml
echo "Step 2 complete: maou_index built (Polars included)"
Step 3: Build maou_rust (PyO3 bindings)
cargo build --manifest-path rust/maou_rust/Cargo.toml
echo "Step 3 complete: maou_rust built"
Step 4: Run maturin (Final linking)
uv run maturin develop
echo "Build complete! Extension installed."
-
Verify Build Success
uv run python -c "from maou._rust.maou_io import hello; print(hello())"
ls -lh target/wheels/
uv run python -c "import maou._rust; print(maou._rust.__file__)"
-
Extreme Memory Constraints (<2GB RAM)
If split build still fails:
export CARGO_INCREMENTAL=0
export RUSTFLAGS="-C codegen-units=1 -C debuginfo=0"
cargo build --manifest-path rust/maou_io/Cargo.toml
cargo build --manifest-path rust/maou_index/Cargo.toml
cargo build --manifest-path rust/maou_rust/Cargo.toml
uv run maturin develop
Build Profiles
Development Profile (Default)
uv run maturin develop
Configuration:
- Optimization level: 0 (no optimization)
- Codegen units: 1 (sequential)
- Incremental: Enabled
- Debug info: Line tables only
Use cases:
- Regular development iteration
- Testing Rust changes
- Local debugging
Performance:
- Build time: 3-5 minutes
- Peak memory: 1.0-1.5GB
Release Profile (Optimized)
uv run maturin develop --release
Configuration:
- Optimization level: 3 (maximum)
- Codegen units: 1 (sequential)
- LTO: Thin (link-time optimization)
- Debug info: Stripped
Use cases:
- Production deployment
- Performance benchmarking
- Final testing before release
Performance:
- Build time: 5-8 minutes
- Peak memory: 1.5-2.0GB
- Binary size: 30-40% smaller than dev
Balanced Profile (Memory-Optimized)
CARGO_PROFILE=mem-opt uv run maturin develop
Configuration:
- Optimization level: 2 (moderate)
- Codegen units: 1
- LTO: Thin
- Incremental: Enabled
Use cases:
- CI/CD builds with memory limits
- Testing optimization impact
- Balancing speed and memory
Performance:
- Build time: 4-6 minutes
- Peak memory: 1.2-1.7GB
Success Criteria
Build succeeds when ALL of the following are met:
- ✓ Build completes without OOM errors
- ✓ Peak memory usage < 1.5GB (dev), < 2.0GB (release)
- ✓ Build time < 10 minutes (split builds acceptable if needed)
- ✓ Python extension imports successfully
- ✓ Extension verification succeeds:
hello() returns expected message
- ✓ No compilation warnings about missing features or dtypes
Common Scenarios
Scenario 1: Initial DevContainer Setup
Context: First-time Rust backend setup in DevContainer (2-core, 3GB RAM)
Commands:
bash scripts/dev-init.sh
uv run maturin develop
uv run python -c "from maou._rust.maou_io import hello; print(hello())"
uv run pytest tests/ -k rust -v
Expected outcome:
- Build completes in 3-5 minutes
- Peak memory ~1.2GB
- All tests pass
Scenario 2: Google Colab Rust Setup
Context: Building Rust extension in Google Colab (limited RAM, non-interactive shell)
Commands:
!curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && \
export PATH="$HOME/.cargo/bin:$PATH" && \
export CARGO_BUILD_JOBS=1 && \
export RUSTFLAGS="-C codegen-units=1 -C incremental=1" && \
uv run maturin develop
!uv run python -c "from maou._rust.maou_io import hello; print(hello())"
Expected outcome:
- Build completes in one cell (no PATH persistence issues)
- Peak memory ~1.5GB
- Import verification succeeds
Scenario 3: Recovering from OOM Failure
Context: Standard build failed with "signal: 9, SIGKILL: kill" or "signal: 15, SIGTERM" error
Diagnostic commands:
dmesg | grep -i "killed process" | tail -5
free -h && df -h
cargo clean
export CARGO_BUILD_JOBS=1
export CARGO_INCREMENTAL=1
export RUSTFLAGS="-C codegen-units=1"
cargo build --manifest-path rust/maou_io/Cargo.toml
cargo build --manifest-path rust/maou_index/Cargo.toml
cargo build --manifest-path rust/maou_rust/Cargo.toml
uv run maturin develop
Expected outcome:
- Sequential builds succeed with <1.5GB peak each
- Final maturin step completes in <1 minute (cached deps)
Scenario 4: CI/CD Build Optimization
Context: GitHub Actions runner with 7GB RAM limit, optimizing build time
Commands:
CARGO_PROFILE=mem-opt uv run maturin develop --release
ls -lh target/wheels/*.whl
Expected outcome:
- Build completes in 4-6 minutes
- Peak memory ~1.7GB
- Wheel size ~5-8MB
Scenario 5: Updating Polars/Arrow Dependencies
Context: Adding new Polars dtype or updating Arrow version
Workflow:
uv add "polars>=1.2.0"
grep "dtype-" Cargo.toml
cargo clean
uv run maturin develop
uv run python -c "from maou.domain.data.schema import get_hcpe_polars_schema; print(get_hcpe_polars_schema())"
Expected outcome:
- Memory usage stays <1.5GB (minimal features)
- Schema validation passes
- No dtype-related compilation errors
Troubleshooting
Issue 1: OOM During polars-core Compilation
Symptoms:
Compiling polars-core v0.45.1
signal: 9, SIGKILL: kill
or
Compiling polars-core v0.45.1
signal: 15, SIGTERM: termination signal
Diagnosis:
grep "dtype-full" Cargo.toml
free -h
dmesg | grep -i oom | tail -5
Solutions:
A. Use split workspace build (RECOMMENDED):
cargo build --manifest-path rust/maou_io/Cargo.toml
cargo build --manifest-path rust/maou_index/Cargo.toml
cargo build --manifest-path rust/maou_rust/Cargo.toml
uv run maturin develop
B. Disable incremental compilation temporarily:
export CARGO_INCREMENTAL=0
cargo clean
uv run maturin develop
C. Verify minimal dtype features:
grep "dtype-" Cargo.toml
Issue 2: Feature Flag Conflict (dtype-u64)
Symptoms:
error: failed to select a version for `polars`
package `maou_index` depends on `polars` with feature `dtype-u64` but `polars` does not have that feature
Diagnosis:
uv pip show polars | grep "version"
cargo tree --manifest-path rust/maou_index/Cargo.toml -e features | grep dtype
Solutions:
A. Remove dtype-u64 (u64 is a core type):
cargo clean
uv run maturin develop
B. Verify workspace dependencies:
features = [
"lazy",
"ipc",
"dtype-i8",
"dtype-i16",
"dtype-u8",
"dtype-u16",
"dtype-date",
]
Issue 3: Incremental Build Cache Corruption
Symptoms:
internal compiler error: ... during incr comp
or
error: could not compile `polars-core` (lib) due to previous error
Diagnosis:
du -sh target/debug/incremental/
ls -la target/debug/incremental/*/
Solutions:
A. Clear incremental cache:
rm -rf target/debug/incremental/
uv run maturin develop
B. Rebuild from scratch:
cargo clean
uv run maturin develop
C. Disable incremental if persistent:
export CARGO_INCREMENTAL=0
uv run maturin develop
Issue 4: maturin Rebuild Not Detecting Changes
Symptoms:
Rust code modified but maturin develop doesn't rebuild
Finished `dev` profile in 0.05s
Diagnosis:
git status rust/
ls -la target/wheels/
ls -lt target/debug/lib_rust.so
Solutions:
A. Force rebuild:
cargo clean
uv run maturin develop
B. Use cargo directly first:
cargo build --manifest-path rust/maou_rust/Cargo.toml
uv run maturin develop
C. Clear wheels cache:
rm -rf target/wheels/
uv run maturin develop
Issue 5: Linker Errors (lld not found)
Symptoms:
error: linking with `cc` failed
/usr/bin/ld: cannot find -llld
or
error: linker `clang` not found
Diagnosis:
which lld
lld --version
which clang
clang --version
Solutions:
A. Install lld and clang:
sudo apt-get update
sudo apt-get install -y lld clang
B. Fallback to default linker temporarily:
export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=gcc
uv run maturin develop
Issue 6: Split Build Failed on Second Crate
Symptoms:
Building rust/maou_index...
error: failed to select a version for `polars`
package `maou_index` depends on `polars` with feature `dtype-u64`
Diagnosis:
echo $?
cargo tree --manifest-path rust/maou_index/Cargo.toml --features | grep polars
Solutions:
A. Feature flag issue - verify workspace dependencies:
grep "dtype-" Cargo.toml
B. Cache conflict - clean and retry:
cargo clean
cargo build --manifest-path rust/maou_io/Cargo.toml
cargo build --manifest-path rust/maou_index/Cargo.toml
C. Verify previous crate built successfully:
ls -lh target/debug/libmaou_io.rlib
cargo build --manifest-path rust/maou_io/Cargo.toml
Issue 7: Build Succeeded But Import Fails
Symptoms:
>>> from maou._rust.maou_io import hello
ImportError: cannot import name 'hello' from 'maou._rust.maou_io'
or
>>> from maou._rust.maou_io import hello
ModuleNotFoundError: No module named 'maou._rust'
Diagnosis:
ls -lh target/debug/lib_rust.so
uv run python -c "import maou._rust; print(maou._rust.__file__)"
uv run pip list | grep maou
Solutions:
A. maturin didn't install the extension:
uv run maturin develop --force
uv run python -c "from maou._rust.maou_io import hello; print(hello())"
B. Wrong Python environment:
uv run which python
uv run maturin develop
C. Module name mismatch:
uv run python -c "import maou._rust; print(dir(maou._rust))"
uv run python -c "import sys; import maou._rust; print(sys.modules['maou._rust'].__path__)"
grep "name = " rust/maou_rust/Cargo.toml
Memory Optimization Details
Automatic Optimizations (Pre-configured)
The project includes these optimizations by default:
1. Environment Variables (scripts/dev-init.sh):
CARGO_BUILD_JOBS=1 - Single parallel job
CARGO_INCREMENTAL=1 - Reuse artifacts between builds
RUSTFLAGS="-C codegen-units=1 -C incremental=1" - Sequential compilation
2. Build Profiles (Cargo.toml):
codegen-units = 1 for all profiles
- Thin LTO for release builds
- Optimized debug info settings
3. Minimal Feature Flags:
- Polars: Only 5 dtypes (i8, i16, u8, u16, date)
- Arrow: No prettyprint feature
- 800MB-1.2GB memory savings vs dtype-full
4. Optimized Linker (.cargo/config.toml):
- Uses lld (LLVM linker) for faster linking
- Lower memory usage than default ld
Performance Impact
| Metric | Before | After | Improvement |
|---|
| Peak Memory | 3.0-3.5GB | 1.0-1.5GB | 60-70% reduction |
| OOM Rate | Frequent | <5% | 95%+ success |
| Dev Build Time | 1-2 min | 3-5 min | Acceptable tradeoff |
| Release Build Time | 2-3 min | 5-8 min | Acceptable tradeoff |
Feature Flag Rationale
Used dtypes (5 total):
dtype-i8: Board piece types, move deltas
dtype-i16: Evaluation scores (centipawns)
dtype-u8: Board square representations (0-255)
dtype-u16: Move labels, piece counts
dtype-date: Timestamp fields
- Note:
u64 is a core type (no feature flag needed for position hash IDs)
Excluded dtypes (12+):
- f32, f64 - Not needed for integer game data
- i32, i64 - Covered by smaller types
- Decimal types - Not used in game records
- String types - Handled separately
- Time types - Only date is needed
Evidence: Analyzed actual usage in:
src/maou/domain/data/schema.py (Polars schemas)
rust/maou_index/src/index.rs (DataFrame operations)
When to Use
- Initial Rust backend setup in DevContainer
- Building in memory-constrained environments (2-4GB RAM)
- Google Colab / Jupyter notebook Rust builds
- CI/CD pipelines with memory limits
- Recovering from OOM build failures
- Debugging maturin build issues
- After updating Polars/Arrow dependencies
- Verifying build configuration correctness
Integration with Other Skills
Runs Before:
qa-pipeline-automation - Build Rust before running Python tests
benchmark-execution - Build optimized release for benchmarking
cloud-integration-tests - Rust backend needed for cloud I/O tests
Uses:
dependency-update-helper - For updating Polars/Arrow/PyO3 versions
Coordinate With:
feature-branch-setup - Build Rust backend after branch creation
pr-preparation-checks - Verify Rust builds succeed in CI
Common Workflows
Workflow 1: Initial Setup + QA
uv run maturin develop
uv run ruff format src/ && uv run ruff check src/ --fix && uv run isort src/ && uv run mypy src/ && uv run pytest
Workflow 2: Dependency Update + Rebuild
uv add "polars>=1.2.0"
cargo clean
uv run maturin develop
uv run pytest tests/ -k rust
Workflow 3: Release Build + Benchmark
uv run maturin develop --release
uv run python -m maou.infra.utility.benchmark_polars_io --num-records 50000
Workflow 4: Cloud Testing Setup
uv run maturin develop
TEST_GCP=true uv run pytest tests/integration/ -k gcs
TEST_AWS=true uv run pytest tests/integration/ -k s3
Context Reduction
Using this skill reduces context usage by ~65% compared to manual troubleshooting:
- Manual approach: ~15 diagnostic commands + documentation lookup + trial-and-error (~2500 tokens)
- Skill activation: Single invocation + structured workflow (~900 tokens)
- Benefit: Automated OOM diagnostics, pre-configured solutions, memory monitoring
References
- CLAUDE.md: Memory-Constrained Build Configuration (lines 229-400)
- CLAUDE.md: Rust Backend Development (lines 146-228)
- CLAUDE.md: Initial Rust Setup (lines 150-211)
.cargo/config.toml: Global build settings
Cargo.toml: Build profiles and feature flags
scripts/dev-init.sh: Environment variable setup
- Cargo documentation: https://doc.rust-lang.org/cargo/
- maturin documentation: https://www.maturin.rs/