diff --git a/README.md b/README.md index 48492fd..df1d46a 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,40 @@ ### Building +You can build the project using the included build script or directly with dotnet CLI: + +#### Using build.bat (Windows) + +```bash +build.bat [options] +``` + +Available options: + +- `--all`: Build for all platforms, including benchmarks and NuGet package +- `--windows`: Build for Windows (default) +- `--linux`: Build for Linux +- `--mac`: Build for macOS +- `--benchmarks`: Build the ChunkMark benchmarking tool +- `--nuget`: Create a NuGet package +- `--docs`: Generate documentation +- `--debug`: Build in Debug configuration (Release is default) + +Examples: + +```bash +# Build for all platforms +build.bat --all + +# Build for Windows and Linux +build.bat --windows --linux + +# Build benchmarks in debug mode +build.bat --benchmarks --debug +``` + +#### Using dotnet CLI + ```bash dotnet build src/AdvChkSys/AdvChkSys.csproj ``` @@ -72,33 +106,6 @@ See [`src/bindings/python/README.md`](src/bindings/python/README.md) for usage. --- -## Project Structure - -``` -advchksys/ - src/ - AdvChkSys/ - Chunk/ - Manager/ - Constraints/ - Events/ - Interfaces/ - Resources/ - Serialization/ - Threading/ - Util/ - AdvChkSys.csproj - bindings/ - python/ - godot/ - tests/ - AdvChkSys.Tests/ - README.md - LICENSE -``` - ---- - ## Documentation - API documentation can be generated with [DocFX](https://dotnet.github.io/docfx/). @@ -123,4 +130,32 @@ This project is licensed under the MIT License. See [LICENSE](LICENSE) for detai Pull requests and issues are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) if available, or open an issue to discuss your ideas. +--- + +## System Requirements + +- Windows, Linux, or macOS operating system +- .NET 5.0 or higher +- Sufficient memory for the requested benchmark parameters (e.g., 3D benchmark with 1024 chunks of size 384×384×384 would require approximately 54-60 GB of RAM) (e.g., 3D benchmark with 1000 chunks of size 32×32×32 would require approximately 125 MB of RAM) +- Math for 1024 chunks at a size of 384x384x384. + +### Memory Calculation + +For 1024 chunks at a size of 384×384×384: + +```python +###Py used for COLORING### +# Calculate cells per chunk +cells_per_chunk = 384 × 384 × 384 = 56,623,104 cells + +# Calculate total bytes +total_bytes = cells_per_chunk × 1024 chunks = 57,972,964,416 bytes + +# Convert to GB +total_GB = total_bytes / 1024 / 1024 / 1024 = 54.2 GB + +# Add 5-20% overhead for metadata, references, and system overhead +final_estimate = 54.2 GB × (1.05 to 1.20) = 56.9 to 65.0 GB +``` + --- \ No newline at end of file diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..e656423 --- /dev/null +++ b/build.bat @@ -0,0 +1,231 @@ +@echo off +setlocal enabledelayedexpansion + +:: AdvChkSys Build Script +:: ====================== + +:: Set colors for console output +set "RESET=[0m" +set "BRIGHT=[1m" +set "RED=[91m" +set "GREEN=[92m" +set "YELLOW=[93m" +set "BLUE=[94m" +set "MAGENTA=[95m" +set "CYAN=[96m" +set "WHITE=[97m" + +:: Set build parameters +set "PROJECT_DIR=src\AdvChkSys" +set "BENCHMARKS_DIR=src\AdvChkSys.Benchmarks" +set "OUTPUT_DIR=build" +set "VERSION=0.1.8" + +:: Create build directory if it doesn't exist +if not exist "%OUTPUT_DIR%" mkdir "%OUTPUT_DIR%" + +:: Display header +echo %BRIGHT%%CYAN%╔══════════════════════════════════════════════════════════════╗%RESET% +echo %BRIGHT%%CYAN%║ ADVANCED CHUNK SYSTEM BUILD ║%RESET% +echo %BRIGHT%%CYAN%╚══════════════════════════════════════════════════════════════╝%RESET% +echo. +echo %BRIGHT%%WHITE%Version: %VERSION%%RESET% +echo %BRIGHT%%WHITE%Date: %DATE% %TIME%%RESET% +echo. + +:: Check for .NET SDK +echo %YELLOW%Checking for .NET SDK...%RESET% +dotnet --version > nul 2>&1 +if %ERRORLEVEL% neq 0 ( + echo %RED%Error: .NET SDK not found. Please install the .NET SDK.%RESET% + exit /b 1 +) +echo %GREEN%✓ .NET SDK found%RESET% +echo. + +:: Parse command line arguments +set "BUILD_WINDOWS=true" +set "BUILD_LINUX=false" +set "BUILD_MAC=false" +set "BUILD_BENCHMARKS=false" +set "BUILD_NUGET=false" +set "BUILD_DOCS=false" +set "CONFIG=Release" + +:parse_args +if "%~1"=="" goto end_parse_args +if /i "%~1"=="--all" ( + set "BUILD_WINDOWS=true" + set "BUILD_LINUX=true" + set "BUILD_MAC=true" + set "BUILD_BENCHMARKS=true" + set "BUILD_NUGET=true" + set "BUILD_DOCS=true" +) else if /i "%~1"=="--windows" ( + set "BUILD_WINDOWS=true" +) else if /i "%~1"=="--linux" ( + set "BUILD_LINUX=true" +) else if /i "%~1"=="--mac" ( + set "BUILD_MAC=true" +) else if /i "%~1"=="--benchmarks" ( + set "BUILD_BENCHMARKS=true" +) else if /i "%~1"=="--nuget" ( + set "BUILD_NUGET=true" +) else if /i "%~1"=="--docs" ( + set "BUILD_DOCS=true" +) else if /i "%~1"=="--debug" ( + set "CONFIG=Debug" +) +shift +goto parse_args +:end_parse_args + +:: Display build configuration +echo %BRIGHT%%MAGENTA%Build Configuration:%RESET% +echo %MAGENTA%• Configuration: %CONFIG%%RESET% +echo %MAGENTA%• Windows: %BUILD_WINDOWS%%RESET% +echo %MAGENTA%• Linux: %BUILD_LINUX%%RESET% +echo %MAGENTA%• macOS: %BUILD_MAC%%RESET% +echo %MAGENTA%• Benchmarks: %BUILD_BENCHMARKS%%RESET% +echo %MAGENTA%• NuGet Package: %BUILD_NUGET%%RESET% +echo %MAGENTA%• Documentation: %BUILD_DOCS%%RESET% +echo. + +:: Clean previous builds +echo %YELLOW%Cleaning previous builds...%RESET% +if exist "%PROJECT_DIR%\bin" rd /s /q "%PROJECT_DIR%\bin" +if exist "%PROJECT_DIR%\obj" rd /s /q "%PROJECT_DIR%\obj" +if exist "%BENCHMARKS_DIR%\bin" rd /s /q "%BENCHMARKS_DIR%\bin" +if exist "%BENCHMARKS_DIR%\obj" rd /s /q "%BENCHMARKS_DIR%\obj" +echo %GREEN%✓ Clean completed%RESET% +echo. + +:: Restore packages +echo %YELLOW%Restoring packages...%RESET% +dotnet restore "%PROJECT_DIR%\AdvChkSys.csproj" +if %ERRORLEVEL% neq 0 ( + echo %RED%✗ Package restore failed%RESET% + exit /b 1 +) +echo %GREEN%✓ Packages restored%RESET% +echo. + +:: Build for Windows +if "%BUILD_WINDOWS%"=="true" ( + echo %BRIGHT%%BLUE%Building for Windows...%RESET% + dotnet build "%PROJECT_DIR%\AdvChkSys.csproj" -c %CONFIG% -r win-x64 --no-restore + if %ERRORLEVEL% neq 0 ( + echo %RED%✗ Windows build failed%RESET% + exit /b 1 + ) + + :: Copy Windows build to output directory + if not exist "%OUTPUT_DIR%\windows" mkdir "%OUTPUT_DIR%\windows" + copy "%PROJECT_DIR%\bin\%CONFIG%\netstandard2.1\AdvChkSys.dll" "%OUTPUT_DIR%\windows\" + copy "%PROJECT_DIR%\bin\%CONFIG%\netstandard2.1\AdvChkSys.xml" "%OUTPUT_DIR%\windows\" + + echo %GREEN%✓ Windows build completed%RESET% + echo. +) + +:: Build for Linux +if "%BUILD_LINUX%"=="true" ( + echo %BRIGHT%%BLUE%Building for Linux...%RESET% + dotnet build "%PROJECT_DIR%\AdvChkSys.csproj" -c %CONFIG% -r linux-x64 --no-restore + if %ERRORLEVEL% neq 0 ( + echo %RED%✗ Linux build failed%RESET% + exit /b 1 + ) + + :: Copy Linux build to output directory + if not exist "%OUTPUT_DIR%\linux" mkdir "%OUTPUT_DIR%\linux" + copy "%PROJECT_DIR%\bin\%CONFIG%\netstandard2.1\AdvChkSys.dll" "%OUTPUT_DIR%\linux\" + copy "%PROJECT_DIR%\bin\%CONFIG%\netstandard2.1\AdvChkSys.xml" "%OUTPUT_DIR%\linux\" + + echo %GREEN%✓ Linux build completed%RESET% + echo. +) + +:: Build for macOS +if "%BUILD_MAC%"=="true" ( + echo %BRIGHT%%BLUE%Building for macOS...%RESET% + dotnet build "%PROJECT_DIR%\AdvChkSys.csproj" -c %CONFIG% -r osx-x64 --no-restore + if %ERRORLEVEL% neq 0 ( + echo %RED%✗ macOS build failed%RESET% + exit /b 1 + ) + + :: Copy macOS build to output directory + if not exist "%OUTPUT_DIR%\macos" mkdir "%OUTPUT_DIR%\macos" + copy "%PROJECT_DIR%\bin\%CONFIG%\netstandard2.1\AdvChkSys.dll" "%OUTPUT_DIR%\macos\" + copy "%PROJECT_DIR%\bin\%CONFIG%\netstandard2.1\AdvChkSys.xml" "%OUTPUT_DIR%\macos\" + + echo %GREEN%✓ macOS build completed%RESET% + echo. +) + +:: Build benchmarks +if "%BUILD_BENCHMARKS%"=="true" ( + echo %BRIGHT%%BLUE%Building ChunkMark benchmarks...%RESET% + dotnet publish "%BENCHMARKS_DIR%\AdvChkSys.Benchmarks.csproj" -c %CONFIG% -r win-x64 --self-contained true -p:PublishSingleFile=true -p:PublishTrimmed=true + if %ERRORLEVEL% neq 0 ( + echo %RED%✗ Benchmark build failed%RESET% + exit /b 1 + ) + + :: Copy benchmark to output directory + if not exist "%OUTPUT_DIR%\benchmarks" mkdir "%OUTPUT_DIR%\benchmarks" + copy "%BENCHMARKS_DIR%\bin\%CONFIG%\net6.0\win-x64\publish\ChunkMark.exe" "%OUTPUT_DIR%\benchmarks\" + + echo %GREEN%✓ Benchmarks built%RESET% + echo. +) + +:: Build NuGet package +if "%BUILD_NUGET%"=="true" ( + echo %BRIGHT%%BLUE%Building NuGet package...%RESET% + dotnet pack "%PROJECT_DIR%\AdvChkSys.csproj" -c %CONFIG% --no-build --output "%OUTPUT_DIR%\nuget" + if %ERRORLEVEL% neq 0 ( + echo %RED%✗ NuGet package creation failed%RESET% + exit /b 1 + ) + echo %GREEN%✓ NuGet package created%RESET% + echo. +) + +:: Build documentation +if "%BUILD_DOCS%"=="true" ( + echo %BRIGHT%%BLUE%Building documentation...%RESET% + echo %YELLOW%Documentation generation not implemented yet.%RESET% + echo. +) + +:: Display summary +echo %BRIGHT%%CYAN%╔══════════════════════════════════════════════════════════════╗%RESET% +echo %BRIGHT%%CYAN%║ BUILD SUMMARY ║%RESET% +echo %BRIGHT%%CYAN%╚══════════════════════════════════════════════════════════════╝%RESET% +echo. +echo %BRIGHT%%GREEN%Build completed successfully!%RESET% +echo. +echo %BRIGHT%%WHITE%Output files:%RESET% + +if "%BUILD_WINDOWS%"=="true" ( + echo %WHITE%• Windows: %OUTPUT_DIR%\windows\AdvChkSys.dll%RESET% +) +if "%BUILD_LINUX%"=="true" ( + echo %WHITE%• Linux: %OUTPUT_DIR%\linux\AdvChkSys.dll%RESET% +) +if "%BUILD_MAC%"=="true" ( + echo %WHITE%• macOS: %OUTPUT_DIR%\macos\AdvChkSys.dll%RESET% +) +if "%BUILD_BENCHMARKS%"=="true" ( + echo %WHITE%• Benchmarks: %OUTPUT_DIR%\benchmarks\ChunkMark.exe%RESET% +) +if "%BUILD_NUGET%"=="true" ( + echo %WHITE%• NuGet: %OUTPUT_DIR%\nuget\AdvChkSys.%VERSION%.nupkg%RESET% +) +echo. +echo %BRIGHT%%CYAN%Run the build script with --help for more options.%RESET% +echo. + +endlocal \ No newline at end of file diff --git a/src/AdvChkSys.Benchmarks/AdvChkSys.Benchmarks.csproj b/src/AdvChkSys.Benchmarks/AdvChkSys.Benchmarks.csproj index 5257abc..bca0de2 100644 --- a/src/AdvChkSys.Benchmarks/AdvChkSys.Benchmarks.csproj +++ b/src/AdvChkSys.Benchmarks/AdvChkSys.Benchmarks.csproj @@ -3,13 +3,22 @@ Exe net9.0 - ChunkMark - latest enable + ChunkMark + ChunkMark + + true + true + win-x64 + true + false + true + + \ No newline at end of file diff --git a/src/AdvChkSys.Benchmarks/ChunkMark.cs b/src/AdvChkSys.Benchmarks/ChunkMark.cs index 7c1bd1c..f09c5c3 100644 --- a/src/AdvChkSys.Benchmarks/ChunkMark.cs +++ b/src/AdvChkSys.Benchmarks/ChunkMark.cs @@ -415,9 +415,11 @@ namespace ChunkMark var constraints = new WorldConstraints { MinChunkX = 0, - MaxChunkX = 9999, + MaxChunkX = 50000, MinChunkY = 0, - MaxChunkY = 9999, + MaxChunkY = 50000, + MinChunkZ = 0, + MaxChunkZ = 50000, MaxLoadedChunks = maxLoaded }; var manager = new ChunkManager3D(constraints, maxLoaded); @@ -871,6 +873,31 @@ namespace ChunkMark logContent.AppendLine($"3D Memory Efficiency: {FormatByteSize(bytesPerChunk3D)}/chunk"); } } + // Detailed Chunk Info + logContent.AppendLine(); + logContent.AppendLine("Detailed Chunk Information:"); + logContent.AppendLine("------------------------------------------------------------------"); + logContent.AppendLine($"Active Chunks (reported by ChunkResourceManager): {memoryReport.ActiveChunkCount:N0}"); + + // Get counts from results + int total2DChunks = _results.Where(r => r.TestName.Contains("2D")).Sum(r => r.ChunkCount); + int total3DChunks = _results.Where(r => r.TestName.Contains("3D")).Sum(r => r.ChunkCount); + int totalChunks = total2DChunks + total3DChunks; + + logContent.AppendLine($"Total 2D Chunks Created: {total2DChunks:N0}"); + logContent.AppendLine($"Total 3D Chunks Created: {total3DChunks:N0}"); + logContent.AppendLine($"Total Chunks Created: {totalChunks:N0}"); + + if (memoryReport.ActiveChunkCount != totalChunks) + { + logContent.AppendLine(); + logContent.AppendLine("Possible reasons for the difference:"); + logContent.AppendLine("1. Chunk eviction due to LRU cache capacity limits"); + logContent.AppendLine("2. Chunks unloaded during benchmark cleanup"); + logContent.AppendLine("3. All-air chunks using flyweight pattern (counted once)"); + logContent.AppendLine("4. Garbage collection removing unreferenced chunks"); + } + // Write the log to file File.WriteAllText(logFilePath, logContent.ToString()); diff --git a/src/AdvChkSys.Benchmarks/README.md b/src/AdvChkSys.Benchmarks/README.md index ee0ff93..6b7e861 100644 --- a/src/AdvChkSys.Benchmarks/README.md +++ b/src/AdvChkSys.Benchmarks/README.md @@ -101,7 +101,23 @@ ChunkMark includes memory safety checks to prevent out-of-memory errors. If a be - **Chunks/Second**: Higher is better. Derived metric showing throughput. ## System Requirements - +- Windows, Linux, or macOS operating system - .NET 5.0 or higher -- Sufficient memory for the requested benchmark parameters -- Windows, Linux, or macOS operating system \ No newline at end of file +- Sufficient memory for the requested benchmark parameters (e.g., 3D benchmark with 1024 chunks of size 384×384×384 would require approximately 54-60 GB of RAM) (e.g., 3D benchmark with 1000 chunks of size 32×32×32 would require approximately 125 MB of RAM) +- Math for 1024 chunks at a size of 384x384x384. + +### Memory Calculation +For 1024 chunks at a size of 384×384×384: +```python +# Calculate cells per chunk +cells_per_chunk = 384 × 384 × 384 = 56,623,104 cells + +# Calculate total bytes +total_bytes = cells_per_chunk × 1024 chunks = 57,972,964,416 bytes + +# Convert to GB +total_GB = total_bytes / 1024 / 1024 / 1024 = 54.2 GB + +# Add 5-20% overhead for metadata, references, and system overhead +final_estimate = 54.2 GB × (1.05 to 1.20) = 56.9 to 65.0 GB +``` \ No newline at end of file diff --git a/src/AdvChkSys/AdvChkSys.cs b/src/AdvChkSys/AdvChkSys.cs index 9e3b98d..2ef2694 100644 --- a/src/AdvChkSys/AdvChkSys.cs +++ b/src/AdvChkSys/AdvChkSys.cs @@ -17,7 +17,7 @@ namespace AdvChkSys /// /// The current version of the AdvChkSys library. /// - public static string Version => "0.1.0"; + public static string Version => "0.1.8"; /// /// Creates a new WorldConstraints object. diff --git a/src/AdvChkSys/Constraints/WorldConstraints.cs b/src/AdvChkSys/Constraints/WorldConstraints.cs index bf5819d..7b97766 100644 --- a/src/AdvChkSys/Constraints/WorldConstraints.cs +++ b/src/AdvChkSys/Constraints/WorldConstraints.cs @@ -28,6 +28,16 @@ public class WorldConstraints /// public int? MaxChunkY { get; set; } + /// + /// If set, the minimum allowed chunk Z coordinate (inclusive). + /// + public int? MinChunkZ { get; set; } + + /// + /// If set, the maximum allowed chunk Z coordinate (inclusive). + /// + public int? MaxChunkZ { get; set; } + /// /// If set, the maximum number of chunks allowed to be loaded in memory at once. /// diff --git a/src/AdvChkSys/Manager/ChunkManager3D.cs b/src/AdvChkSys/Manager/ChunkManager3D.cs index 37c629b..149aa20 100644 --- a/src/AdvChkSys/Manager/ChunkManager3D.cs +++ b/src/AdvChkSys/Manager/ChunkManager3D.cs @@ -1,13 +1,15 @@ #nullable enable using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; using System.Threading.Tasks; +using System; using AdvChkSys.Chunk; +using AdvChkSys.Constraints; using AdvChkSys.Events; using AdvChkSys.Interfaces; using AdvChkSys.Resources; -using AdvChkSys.Constraints; using AdvChkSys.Util; -using System; namespace AdvChkSys.Manager { @@ -120,26 +122,31 @@ namespace AdvChkSys.Manager return chunk; } + // Note: This method may cause trimming warnings when publishing as a trimmed app private void OnChunkEvicted((int, int, int) key, Chunk3D chunk) { if (chunk == null) return; - var arrField = chunk.GetType().GetField("_data", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); - T[,,]? arr = null; - if (arrField != null) + // Instead of using reflection, use the GetDataArray method if available + T[,,]? arr = chunk.GetDataArray(); + + // If GetDataArray returned null, fall back to reflection + if (arr == null) { - arr = arrField.GetValue(chunk) as T[,,]; + var arrField = chunk.GetType().GetField("_data", BindingFlags.NonPublic | BindingFlags.Instance); + if (arrField != null) + { + arr = arrField.GetValue(chunk) as T[,,]; + } } + if (!chunk.IsAllAir && arr != null) { Chunk3D.ReturnArray(arr); } - if (chunk != null) - { - ChunkResourceManager.ReleaseChunk(chunk); - ChunkEvents.OnChunkUnloaded(chunk); - } + ChunkResourceManager.ReleaseChunk(chunk); + ChunkEvents.OnChunkUnloaded(chunk); } ///