Main ideas for different versions LS0: "Get it working" → Focus on functional completeness LS1: "Make it faster" → Introduces concurrency and basic caching but retains some inefficiencies. LS101: "Optimize for scale" → Prioritizes memory efficiency, thread safety, and user experience.
Repetition times are recently changed from row * col to 2 * row * col for better eliminating randomness with adaptable size.
LifeSimulation0 failed due to storing full grid states in memory (ArrayList with deep copies). LifeSimulation1/101 use incremental updates via tempGrid in Landscape.advance() and avoid storing entire grid histories, solving memory overflow.
LifeSimulation1 fixed getNeighbors() in Landscape to prevent out-of-bounds access LifeSimulation0 had a bug in getNeighbors() causing edge cells to reference invalid indices.
Resolving flickering artifacts, LifeSimulation1/101 fix this via: if (x >= 0 && x < rows && y >= 0 && y < cols) { ... } Experimental Setup Simulation Version Grid Dimensions Command Parameters Execution Status LifeSimulation0 4×4 4 1000 Failed (OOM and index out of bound) LifeSimulation1 4×4 4 1000 Failed (index out of bound) LifeSimulation101 5×5 5 1000 Successful OOM in LifeSimulation0: storing full grid states in memory for all iterations instead of using incremental updates and boundary error. Logic error in LifeSimulation1: Incorrect boundary checks in getNeighbors(), leading to invalid neighbor counts for edge cells. Flaw LifeSimulation0 LifeSimulation1 Fix LifeSimulation101 Enhancement Grid State Storage Stored full grid states for all iterations → OOM Uses temporary grid buffers to avoid history storage Added configurable grid parameters to decouple from static fields Neighbor Boundary Checks No boundary checks → Logic errors Explicit boundary checks in getNeighbors() Maintained checks with optimized grid access patterns Concurrency Control synchronized methods → Contention AtomicBoolean for recording state Platform.runLater() for UI thread safety Data Aggregation Sequential loop-based simulation runs Parallel IntStream for chance-value iterations Cache-based result reuse (simulationCache) for fewer runs Visualization Performance Direct landscape.draw() without clearing Added gc.clearRect() in drawLandscape() Optimized mesh indexing and face generation for smoother 3D surfaces
Aspect LifeSimulation0 LifeSimulation1 LifeSimulation101 Caching Strategy No explicit caching → Repeated simulations for same (m, n, chance) Introduced basic cache but no duplicate check during data collection Full cache utilization: Cache checks in simulateForChance() Concurrency Single-threaded data collection → UI freezes during heavy computations Parallel IntStream and CompletableFuture → 50% faster data collection Fine-grained parallelism: Cache-aware parallel streams + atomic updates → faster Memory Management Stores full grid states for all steps → OOM at m=10+ tempGrid pattern in Landscape.advance() → Reduced half memory footprint Cache + tempGrid → Eliminated OOM errors + Reduced over half memory for large grids
UI/UX Hardcoded chart sizes + static controls → Inflexible layout Dynamic chart sizing via CHART_WIDTH/HEIGHT → Basic configurability Constructor parameters + responsive layout → Customizable UI dimensions Thread Safety synchronized methods → Contention in recording thread AtomicBoolean for recording state → Reduced lock contention compareAndSet() for recording + atomic cache updates → Thread-safe without locks 3D Visualization Recomputes mesh for every slider move → Laggy UI response Precomputed meshes for 20% chance intervals → Faster slider updates Cache-driven mesh updates + precomputed vertex arrays → 2x faster 3D rendering Data Structure Map with raw arrays → Inefficient lookups ConcurrentHashMap for cache → Thread-safe access Double caching (simulation + surface mesh) → Reduced redundant computations Error Handling Silent exceptions (e.g., saveSimulationState() swallows IOException) Partial error logging → Inconsistent user feedback Explicit error messages + detailed logging → User-aware debugging
Feature LifeSimulation0 LifeSimulation1 LifeSimulation101 Grid Updates Direct Landscape.draw() calls → High GC pressure tempGrid in advance() → Immutable state transitions Batched GC clears in drawLandscape() → Smooth animations 3D Mesh Generation Recalculates normals for every face → O(n³) complexity Precomputed normals via calculateNormal() → O(n²) complexity Vertex array preallocation + indexed faces → O(n²) with minimal allocations Slider Interaction Rebuilds entire 3D scene on slider move → UI freezes Precompute meshes for 20% intervals → Partial rebuilds Lazy mesh updates (only affected vertices) → Instant slider response Cache Efficiency No cache → 100% redundant runs Basic cache with 50% redundancy due to fixed steps Step-aware cache (tracks steps and chance) → <10% redundant runs Error Resilience save3DModel() ignores exceptions → Silent failures Basic try/catch → Partial error handling Explicit exception handling + retry logic → Robust file operations
Performance Measured from System Monitor Metric LifeSimulation0 LifeSimulation1 LifeSimulation101 3D Mesh Generation (max = 10) 20s 12s 8s Memory Usage (m=12) 2.4GB → OOM at m=13 1.2GB → Runs m=15 300MB → Stable up to m=20 UI Freezing Frequent freezes Occasional lag No visible freezes
LS0: Mixed simulation logic with UI updates → Tight coupling. LS1: Split into simulateForChance() + async data tasks → Decoupled logic. LS101: Service-oriented design (e.g., createSurfaceMesh() as reusable component).
LS0: Synchronized methods → Thread contention. LS1: CompletableFuture + parallelStream() → Task parallelism. LS101: Cache-aware concurrency + atomic updates → Zero race conditions. 3D Rendering Pipeline:
LS0: Per-face normal calculation → CPU-bound. LS1: Precompute normals → GPU-friendly arrays. LS101: Vertex buffer reuse + indexed faces → Direct GPU mapping.
LS1 → LS101 Removed ProgressBar → Simplified UI Lost progress visibility for large grids LS0 → LS1 Requires explicit parameter passing → Steeper learning curve LS1 → LS101 Increased CPU load for large m → Balanced by caching