diff --git a/.gitignore b/.gitignore index 01f9cb9..4e3ffa2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ build/ -.vscode/ \ No newline at end of file +.vscode/ +testapp/ + diff --git a/README.md b/README.md index b0eb586..d47ad59 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,15 @@ * Thread-safe - Safe for concurrent allocations and deallocations * No feature creep inside -## ๐Ÿ“ฆ Downloads +## ๏ฟฝ Documentation + +- **[Getting Started Guide](docs/GETTING_STARTED.md)** - Quick start with easy examples +- **[Integration Guide](docs/INTEGRATION_GUIDE.md)** - Detailed integration instructions +- **[API Reference](docs/API_REFERENCE.md)** - Complete API documentation +- **[Thread Safety](docs/THREAD_SAFETY.md)** - Multi-threading guidelines +- **[Performance Metrics](docs/PERFORMANCE_METRICS.md)** - Performance testing guide + +## ๏ฟฝ๐Ÿ“ฆ Downloads Pre-built binaries are available from the [Releases page](https://github.com/el-dockerr/GhostMem/releases). diff --git a/docs/API_REFERENCE.md b/docs/API_REFERENCE.md index cf887f2..50f38b9 100644 --- a/docs/API_REFERENCE.md +++ b/docs/API_REFERENCE.md @@ -460,6 +460,16 @@ list.push_back(3.14); Configuration structure for customizing GhostMemoryManager behavior, including optional disk-backed storage for compressed pages. +#### Quick Reference + +| Field | Type | Default | Description | +|-------|------|---------|-------------| +| `use_disk_backing` | `bool` | `false` | Enable disk storage instead of in-memory compression | +| `disk_file_path` | `std::string` | `"ghostmem.swap"` | Path to disk file for storing compressed pages | +| `max_memory_pages` | `size_t` | `0` | Max physical pages in RAM (0 = use constant) | +| `compress_before_disk` | `bool` | `true` | Compress pages before writing to disk | +| `enable_verbose_logging` | `bool` | `false` | Enable detailed console debug output | + #### Fields ##### `bool use_disk_backing` @@ -538,6 +548,48 @@ config.compress_before_disk = false; // No compression (faster I/O) --- +##### `bool enable_verbose_logging` +Enable verbose debug logging to console. + +**Default:** `false` (silent operation) + +**Behavior:** +- When `false` (default): GhostMem operates silently with no console output +- When `true`: Outputs detailed operational messages including: + - Initialization status (disk backing, configuration) + - Page eviction events + - Memory allocation/deallocation messages + - Disk I/O operations + - Error and warning messages + +**Performance Impact:** +- Negligible when disabled (default) +- Minor overhead when enabled due to console I/O + +**Use Cases:** +- Development and debugging +- Monitoring memory behavior +- Performance analysis +- Troubleshooting issues + +**Example:** +```cpp +// Silent mode (production) +config.enable_verbose_logging = false; + +// Verbose mode (development/debugging) +config.enable_verbose_logging = true; +``` + +**Sample Output (when enabled):** +``` +[GhostMem] Disk backing enabled: ghostmem.swap (compress=yes) +[GhostMem] Page fully freed: 0x7fff12340000 +[GhostMem] Zombie page freed during eviction: 0x7fff12341000 +``` + +--- + #### Complete Configuration Example ```cpp @@ -550,6 +602,7 @@ int main() { config.disk_file_path = "myapp_ghost.swap"; config.compress_before_disk = true; config.max_memory_pages = 256; // 1MB physical RAM + config.enable_verbose_logging = false; // Silent operation (default) // Initialize before any allocations if (!GhostMemoryManager::Instance().Initialize(config)) { @@ -811,6 +864,7 @@ If a page fault occurs outside ghost memory ranges: ## See Also +- [Getting Started Guide](GETTING_STARTED.md) - Quick start with examples - [Integration Guide](INTEGRATION_GUIDE.md) - How to use GhostMem in your project - [Thread Safety](THREAD_SAFETY.md) - Detailed thread safety documentation - [Main README](../README.md) - Project overview and quick start diff --git a/docs/GETTING_STARTED.md b/docs/GETTING_STARTED.md new file mode 100644 index 0000000..35f60fc --- /dev/null +++ b/docs/GETTING_STARTED.md @@ -0,0 +1,469 @@ +# GhostMem Getting Started Guide + +## Table of Contents +- [Quick Start](#quick-start) +- [Basic Usage](#basic-usage) +- [Configuration Options](#configuration-options) +- [Complete Examples](#complete-examples) +- [Common Use Cases](#common-use-cases) +- [Next Steps](#next-steps) + +--- + +## Quick Start + +Get up and running with GhostMem in under 5 minutes! + +### Step 1: Include Headers + +```cpp +#include "ghostmem/GhostMemoryManager.h" +#include "ghostmem/GhostAllocator.h" +#include +#include +``` + +### Step 2: Use with STL Containers + +```cpp +int main() { + // Create a vector with GhostAllocator + std::vector> vec; + + // Use it like a normal vector - compression happens automatically! + for (int i = 0; i < 10000; i++) { + vec.push_back(i); + } + + // Access elements normally + std::cout << "Value at index 5000: " << vec[5000] << std::endl; + + return 0; +} +``` + +**That's it!** GhostMem will automatically: +- Compress inactive memory pages +- Decompress pages when accessed +- Manage memory limits +- Clean up on program exit + +--- + +## Basic Usage + +### Without Configuration (Default Behavior) + +By default, GhostMem uses **in-memory compression** with these settings: +- Maximum 5 pages (20KB) in physical RAM +- LZ4 compression for evicted pages +- Silent operation (no console output) + +```cpp +#include "ghostmem/GhostAllocator.h" +#include + +int main() { + // No configuration needed - just use it! + std::vector> data; + + for (int i = 0; i < 100000; i++) { + data.push_back(i * 2); + } + + return 0; +} +``` + +### With Custom Configuration + +For more control, initialize GhostMem with a custom configuration: + +```cpp +#include "ghostmem/GhostMemoryManager.h" +#include "ghostmem/GhostAllocator.h" +#include + +int main() { + // Create configuration + GhostConfig config; + config.max_memory_pages = 256; // 1MB physical RAM + + // Initialize before using + if (!GhostMemoryManager::Instance().Initialize(config)) { + std::cerr << "Failed to initialize GhostMem\n"; + return 1; + } + + // Now use GhostAllocator + std::vector> vec; + // ... your code ... + + return 0; +} +``` + +--- + +## Configuration Options + +### GhostConfig Structure + +```cpp +struct GhostConfig { + bool use_disk_backing = false; // Use disk instead of RAM for compressed pages + std::string disk_file_path = "ghostmem.swap"; // Disk file location + size_t max_memory_pages = 0; // Page limit (0 = use default) + bool compress_before_disk = true; // Compress before writing to disk + bool enable_verbose_logging = false; // Enable debug output +}; +``` + +### Memory Limits + +Control how much physical RAM GhostMem uses: + +```cpp +GhostConfig config; + +// Small devices (256KB RAM) +config.max_memory_pages = 64; + +// Medium (1MB RAM) +config.max_memory_pages = 256; + +// Large (100MB RAM) +config.max_memory_pages = 25600; + +GhostMemoryManager::Instance().Initialize(config); +``` + +### Disk-Backed Storage + +Enable disk storage for compressed pages to minimize RAM usage: + +```cpp +GhostConfig config; +config.use_disk_backing = true; // Enable disk backing +config.disk_file_path = "myapp_ghost.swap"; // Custom file path +config.compress_before_disk = true; // Compress before disk write +config.max_memory_pages = 100; // Limit active RAM pages + +if (!GhostMemoryManager::Instance().Initialize(config)) { + std::cerr << "Failed to open disk file\n"; + return 1; +} +``` + +**Benefits:** +- โœ… Reduces RAM footprint significantly +- โœ… Can handle datasets larger than available RAM +- โš ๏ธ Slower than in-memory compression (disk I/O latency) + +**File Location:** +- Relative paths are relative to working directory +- File is created automatically if it doesn't exist +- File is truncated on each program start + +### Verbose Logging + +Enable detailed console output for debugging and monitoring: + +```cpp +GhostConfig config; +config.enable_verbose_logging = true; // Enable debug output + +GhostMemoryManager::Instance().Initialize(config); + +// Now you'll see messages like: +// [GhostMem] Disk backing enabled: ghostmem.swap (compress=yes) +// [GhostMem] Page fully freed: 0x7fff12340000 +// [GhostMem] Zombie page freed during eviction: 0x7fff12341000 +``` + +**When to enable:** +- ๐Ÿ” Debugging memory issues +- ๐Ÿ“Š Monitoring page eviction behavior +- ๐Ÿงช Performance testing + +**Default:** `false` (silent operation) + +--- + +## Complete Examples + +### Example 1: Simple Vector with Default Settings + +```cpp +#include "ghostmem/GhostAllocator.h" +#include +#include + +int main() { + std::vector> numbers; + + // Fill with 10,000 integers + for (int i = 0; i < 10000; i++) { + numbers.push_back(i); + } + + // Access random element + std::cout << "Element 5000: " << numbers[5000] << std::endl; + + return 0; +} +``` + +### Example 2: Disk-Backed with Verbose Logging + +```cpp +#include "ghostmem/GhostMemoryManager.h" +#include "ghostmem/GhostAllocator.h" +#include +#include +#include + +int main() { + // Configure for disk backing with logging + GhostConfig config; + config.use_disk_backing = true; + config.disk_file_path = "data.swap"; + config.max_memory_pages = 5000; // ~20MB RAM limit + config.enable_verbose_logging = true; + + if (!GhostMemoryManager::Instance().Initialize(config)) { + std::cerr << "Initialization failed\n"; + return 1; + } + + std::cout << "GhostMem initialized successfully\n"; + + // Use with vector + std::vector> data; + + for (int i = 0; i < 100000; i++) { + data.push_back(i); + + if (i % 10000 == 0) { + std::cout << "Progress: " << i << " elements\n"; + } + } + + std::cout << "Final size: " << data.size() << std::endl; + std::cout << "Sample value: " << data[50000] << std::endl; + + return 0; +} +``` + +### Example 3: String Processing with Custom Memory Limit + +```cpp +#include "ghostmem/GhostMemoryManager.h" +#include "ghostmem/GhostAllocator.h" +#include +#include +#include + +// Define string type with GhostAllocator +using GhostString = std::basic_string, + GhostAllocator>; + +int main() { + // Configure with custom limits + GhostConfig config; + config.max_memory_pages = 512; // 2MB RAM limit + + GhostMemoryManager::Instance().Initialize(config); + + // Create vector of strings + std::vector> log_lines; + + // Simulate log processing + for (int i = 0; i < 10000; i++) { + GhostString line = GhostString("Log entry #") + + std::to_string(i) + + GhostString(": System operational"); + log_lines.push_back(line); + } + + std::cout << "Processed " << log_lines.size() << " log lines\n"; + std::cout << "First: " << log_lines[0].c_str() << std::endl; + std::cout << "Last: " << log_lines[9999].c_str() << std::endl; + + return 0; +} +``` + +### Example 4: Production Configuration (Silent + Disk) + +```cpp +#include "ghostmem/GhostMemoryManager.h" +#include "ghostmem/GhostAllocator.h" +#include +#include + +int main() { + // Production settings: disk backing, no logging + GhostConfig config; + config.use_disk_backing = true; + config.disk_file_path = "/tmp/myapp.swap"; // Linux/Mac + // config.disk_file_path = "C:\\Temp\\myapp.swap"; // Windows + config.compress_before_disk = true; + config.max_memory_pages = 10000; // ~40MB RAM limit + config.enable_verbose_logging = false; // Silent for production + + if (!GhostMemoryManager::Instance().Initialize(config)) { + // Silent initialization failure handling + std::cerr << "Critical: Memory manager initialization failed\n"; + return 1; + } + + // Application continues silently + std::vector> data; + + // Process large dataset + for (int i = 0; i < 1000000; i++) { + data.push_back(i * i); + } + + std::cout << "Processing complete: " << data.size() << " elements\n"; + + return 0; +} +``` + +--- + +## Common Use Cases + +### IoT Device with Limited RAM + +```cpp +GhostConfig config; +config.max_memory_pages = 32; // Only 128KB RAM +config.use_disk_backing = true; +config.disk_file_path = "/data/ghost.swap"; +config.enable_verbose_logging = false; // Silent on embedded device + +GhostMemoryManager::Instance().Initialize(config); +``` + +### Development/Testing + +```cpp +GhostConfig config; +config.max_memory_pages = 100; // Small limit to force swapping +config.enable_verbose_logging = true; // See what's happening +config.use_disk_backing = false; // Fast in-memory testing + +GhostMemoryManager::Instance().Initialize(config); +``` + +### AI Model Inference + +```cpp +GhostConfig config; +config.max_memory_pages = 50000; // ~200MB active RAM +config.use_disk_backing = true; +config.disk_file_path = "model_cache.swap"; +config.compress_before_disk = true; +config.enable_verbose_logging = false; + +GhostMemoryManager::Instance().Initialize(config); +``` + +### Data Processing Pipeline + +```cpp +GhostConfig config; +config.max_memory_pages = 25600; // ~100MB RAM +config.use_disk_backing = true; +config.disk_file_path = "./pipeline_swap.dat"; +config.enable_verbose_logging = false; + +GhostMemoryManager::Instance().Initialize(config); + +// Use with multiple containers +std::vector> input_buffer; +std::vector> output_buffer; +``` + +--- + +## Next Steps + +### Learn More + +- **[Integration Guide](INTEGRATION_GUIDE.md)** - Detailed integration instructions and build options +- **[API Reference](API_REFERENCE.md)** - Complete API documentation +- **[Thread Safety](THREAD_SAFETY.md)** - Multi-threading guidelines and best practices +- **[Performance Metrics](PERFORMANCE_METRICS.md)** - Performance testing and optimization +- **[Main README](../README.md)** - Project overview and architecture + +### Key Concepts + +1. **Page-based Management**: GhostMem works with 4KB pages +2. **LRU Eviction**: Least recently used pages are compressed first +3. **Transparent Operation**: Page faults trigger automatic decompression +4. **Thread-Safe**: Safe for concurrent allocations and access + +### Best Practices + +โœ… **Do:** +- Initialize with `Initialize()` for custom configuration +- Use disk backing for large datasets or extreme memory constraints +- Test with verbose logging enabled during development +- Choose appropriate `max_memory_pages` for your workload + +โŒ **Don't:** +- Don't call `Initialize()` after starting allocations +- Don't mix GhostAllocator with regular allocators for the same container +- Don't rely on verbose output in production (performance impact) +- Don't forget to handle `Initialize()` failure when disk backing is enabled + +### Troubleshooting + +**Problem: No disk file created** +- Solution: Ensure you call `Initialize(config)` before using `GhostAllocator` +- Solution: Check that `config.use_disk_backing = true` is set + +**Problem: Want to see what's happening** +- Solution: Set `config.enable_verbose_logging = true` + +**Problem: Too much memory usage** +- Solution: Reduce `config.max_memory_pages` +- Solution: Enable `config.use_disk_backing = true` + +**Problem: Performance too slow** +- Solution: Increase `config.max_memory_pages` +- Solution: Use in-memory mode (`use_disk_backing = false`) +- Solution: Disable verbose logging in production + +--- + +## Quick Reference Card + +```cpp +// Minimal usage +std::vector> vec; + +// With disk backing +GhostConfig cfg; +cfg.use_disk_backing = true; +cfg.disk_file_path = "swap.dat"; +GhostMemoryManager::Instance().Initialize(cfg); + +// With verbose logging +cfg.enable_verbose_logging = true; + +// Custom memory limit +cfg.max_memory_pages = 1024; // 4MB RAM +``` + +--- + +**Ready to optimize your memory usage?** Start with the simplest example and add configuration options as needed! + +For comprehensive documentation, see the [API Reference](API_REFERENCE.md) and [Integration Guide](INTEGRATION_GUIDE.md). diff --git a/docs/INTEGRATION_GUIDE.md b/docs/INTEGRATION_GUIDE.md index 3673ca3..e39c667 100644 --- a/docs/INTEGRATION_GUIDE.md +++ b/docs/INTEGRATION_GUIDE.md @@ -1177,6 +1177,7 @@ ulimit -a ## Next Steps +- Start with the [Getting Started Guide](GETTING_STARTED.md) for quick examples - Read the [API Reference](API_REFERENCE.md) for detailed function documentation - Check [Thread Safety](THREAD_SAFETY.md) for multi-threading guidelines - See [examples/](../src/main.cpp) for more code samples diff --git a/docs/PERFORMANCE_METRICS.md b/docs/PERFORMANCE_METRICS.md index 0a7ba4b..ab82d93 100644 --- a/docs/PERFORMANCE_METRICS.md +++ b/docs/PERFORMANCE_METRICS.md @@ -248,6 +248,16 @@ Potential enhancements to metrics tests: GhostMemStats stats = GhostMemoryManager::Instance().GetStatistics(); ``` +## See Also + +- [Getting Started Guide](GETTING_STARTED.md) - Quick start with examples +- [API Reference](API_REFERENCE.md) - Complete API documentation +- [Integration Guide](INTEGRATION_GUIDE.md) - Integration instructions +- [Thread Safety](THREAD_SAFETY.md) - Multi-threading guidelines +- [Main README](../README.md) - Project overview + +--- + ## References - [LZ4 Compression Benchmarks](https://github.com/lz4/lz4) diff --git a/docs/THREAD_SAFETY.md b/docs/THREAD_SAFETY.md index bf8f103..587a367 100644 --- a/docs/THREAD_SAFETY.md +++ b/docs/THREAD_SAFETY.md @@ -620,6 +620,7 @@ void test_concurrent_allocations() { ## See Also +- [Getting Started Guide](GETTING_STARTED.md) - Quick start with examples - [API Reference](API_REFERENCE.md) - Detailed API documentation - [Integration Guide](INTEGRATION_GUIDE.md) - How to use GhostMem - [Main README](../README.md) - Project overview diff --git a/src/ghostmem/GhostMemoryManager.cpp b/src/ghostmem/GhostMemoryManager.cpp index afde6c1..51babaf 100644 --- a/src/ghostmem/GhostMemoryManager.cpp +++ b/src/ghostmem/GhostMemoryManager.cpp @@ -82,16 +82,25 @@ bool GhostMemoryManager::Initialize(const GhostConfig& config) { if (!OpenDiskFile()) { - std::cerr << "[GhostMem] ERROR: Failed to open disk file: " - << config_.disk_file_path << std::endl; + if (config_.enable_verbose_logging) + { + std::cerr << "[GhostMem] ERROR: Failed to open disk file: " + << config_.disk_file_path << std::endl; + } return false; } - std::cout << "[GhostMem] Disk backing enabled: " << config_.disk_file_path - << " (compress=" << (config_.compress_before_disk ? "yes" : "no") << ")" << std::endl; + if (config_.enable_verbose_logging) + { + std::cout << "[GhostMem] Disk backing enabled: " << config_.disk_file_path + << " (compress=" << (config_.compress_before_disk ? "yes" : "no") << ")" << std::endl; + } } else { - std::cout << "[GhostMem] Using in-memory backing store" << std::endl; + if (config_.enable_verbose_logging) + { + std::cout << "[GhostMem] Using in-memory backing store" << std::endl; + } } return true; @@ -308,7 +317,10 @@ void GhostMemoryManager::EvictOldestPage(void *ignore_page) munmap(victim, PAGE_SIZE); #endif - std::cout << "[GhostMem] Zombie page freed during eviction: " << victim << std::endl; + if (config_.enable_verbose_logging) + { + std::cout << "[GhostMem] Zombie page freed during eviction: " << victim << std::endl; + } } else { @@ -439,8 +451,11 @@ void GhostMemoryManager::DeallocateGhost(void* ptr, size_t size) if (alloc_it == allocation_metadata_.end()) { // Allocation not tracked - could be already freed or invalid pointer - std::cerr << "[GhostMem] WARNING: Attempted to deallocate untracked pointer: " - << ptr << std::endl; + if (config_.enable_verbose_logging) + { + std::cerr << "[GhostMem] WARNING: Attempted to deallocate untracked pointer: " + << ptr << std::endl; + } return; } @@ -462,8 +477,11 @@ void GhostMemoryManager::DeallocateGhost(void* ptr, size_t size) auto ref_it = page_ref_counts_.find(page_start); if (ref_it == page_ref_counts_.end()) { - std::cerr << "[GhostMem] ERROR: Page reference count not found for: " - << page_start << std::endl; + if (config_.enable_verbose_logging) + { + std::cerr << "[GhostMem] ERROR: Page reference count not found for: " + << page_start << std::endl; + } continue; } @@ -504,7 +522,10 @@ void GhostMemoryManager::DeallocateGhost(void* ptr, size_t size) munmap(page_start, PAGE_SIZE); #endif - std::cout << "[GhostMem] Page fully freed: " << page_start << std::endl; + if (config_.enable_verbose_logging) + { + std::cout << "[GhostMem] Page fully freed: " << page_start << std::endl; + } } } } diff --git a/src/ghostmem/GhostMemoryManager.h b/src/ghostmem/GhostMemoryManager.h index 3fb1da0..8d3cb05 100644 --- a/src/ghostmem/GhostMemoryManager.h +++ b/src/ghostmem/GhostMemoryManager.h @@ -138,6 +138,17 @@ struct GhostConfig * Default: true (compress before disk write) */ bool compress_before_disk = true; + + /** + * @brief Enable verbose debug logging to console + * + * When true, GhostMem outputs detailed operational messages to console + * including page evictions, disk operations, and memory management events. + * When false (default), all debug output is suppressed for silent operation. + * + * Default: false (silent mode) + */ + bool enable_verbose_logging = false; }; /** diff --git a/src/ghostmem/Version.h b/src/ghostmem/Version.h index 0e2c70b..b3bb1cd 100644 --- a/src/ghostmem/Version.h +++ b/src/ghostmem/Version.h @@ -39,10 +39,10 @@ // Version numbers #define GHOSTMEM_VERSION_MAJOR 1 #define GHOSTMEM_VERSION_MINOR 0 -#define GHOSTMEM_VERSION_PATCH 0 +#define GHOSTMEM_VERSION_PATCH 1 // Version string -#define GHOSTMEM_VERSION_STRING "1.0.0" +#define GHOSTMEM_VERSION_STRING "1.0.1" // Namespace for version info namespace GhostMem { diff --git a/src/main.cpp b/src/main.cpp index 3391166..f898584 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -22,6 +22,7 @@ int main() { config.disk_file_path = "ghostmem_demo.swap"; config.compress_before_disk = true; config.max_memory_pages = 5; // Override default + config.enable_verbose_logging = true; // Enable debug output (optional) if (!GhostMemoryManager::Instance().Initialize(config)) { std::cerr << "Failed to initialize GhostMem with disk backing\n"; diff --git a/tests/test_version.cpp b/tests/test_version.cpp index 05bed8d..fa28710 100644 --- a/tests/test_version.cpp +++ b/tests/test_version.cpp @@ -5,17 +5,17 @@ TEST(VersionConstants) { ASSERT_EQ(GhostMem::GetVersionMajor(), 1); ASSERT_EQ(GhostMem::GetVersionMinor(), 0); - ASSERT_EQ(GhostMem::GetVersionPatch(), 0); + ASSERT_EQ(GhostMem::GetVersionPatch(), 1); } // Test version string TEST(VersionString) { std::string version = GhostMem::GetVersionString(); - ASSERT_TRUE(version == "1.0.0"); + ASSERT_TRUE(version == "1.0.1"); } // Test version number encoding TEST(VersionNumber) { int version = GhostMem::GetVersion(); - ASSERT_EQ(version, 10000); // 1 * 10000 + 0 * 100 + 0 + ASSERT_EQ(version, 10001); // 1 * 10000 + 0 * 100 + 1 }