This solution contains a simple generic in-memory cache manager and two console applications:
-
CacheManager.Core
- Class library with a generic cache manager interface and implementation using
Dictionary<TKey, TValue>. - Types:
ICacheManager<TKey, TValue>: basicPut,TryGet,Remove, andSnapshotoperations.CacheManager<TKey, TValue>: concrete implementation backed byDictionary<TKey, TValue>.- Optional capacity-limited mode with LFU (Least Frequently Used) eviction and LRU (Least Recently Used) as a tie-breaker.
- Default: unlimited capacity (no eviction), created with
new CacheManager<TKey, TValue>(). - Bounded:
new CacheManager<TKey, TValue>(maxEntries: 100)enables LFU+LRU-based eviction when the number of items exceedsmaxEntries.
- Default: unlimited capacity (no eviction), created with
- Optional capacity-limited mode with LFU (Least Frequently Used) eviction and LRU (Least Recently Used) as a tie-breaker.
- Class library with a generic cache manager interface and implementation using
-
CacheManager.OpGenerator
- Console app that generates a randomized sequence of cache operations (PUT / GET / REMOVE).
- Writes them into a text file named
cache_input_operations.txtin the solution root.
-
CacheManager.Tester
- Console app that reads
cache_input_operations.txt, executes the operations on the cache, and then:- Writes the final cache state into
cache_baseline_*.txt(if it does not yet exist). - On subsequent runs, compares the new cache state to the existing
cache_baseline_*.txtto check for consistent behavior. - Supports testing with different cache capacities to validate eviction behavior.
- Writes the final cache state into
- Console app that reads
- .NET SDK 8 (or later compatible) installed.
From a terminal / bash shell, go to the solution folder:
cd /mnt/c/Projects/CacheManagerBy default, the generator creates 1000 operations over 100 keys.
dotnet run --project ./CacheManager.OpGenerator/CacheManager.OpGenerator.csprojYou can optionally pass:
- First argument: number of operations
- Second argument: number of distinct keys
Example (1000000 operations over 10000 keys):
dotnet run --project ./CacheManager.OpGenerator/CacheManager.OpGenerator.csproj -- 1000000 10000This creates or overwrites cache_input_operations.txt in /mnt/c/Projects/CacheManager.
The tester accepts two optional parameters:
- First argument: number of test iterations (how many times to replay
cache_input_operations.txtbefore snapshot/compare). - Second argument: max entries (maximum number of cache entries before eviction kicks in). If omitted or non-positive, the cache is unlimited.
The max entries parameter controls the maximum number of entries the cache can hold before eviction occurs:
-
Unlimited entries (default):
max entriesis omitted, null, or non-positive- No eviction occurs regardless of cache size
- Creates snapshot file:
cache_baseline_unlimited.txt - Example:
dotnet run --project ./CacheManager.Tester/CacheManager.Tester.csproj
-
Limited entries:
max entriesis a positive integer- When cache exceeds this limit, LFU+LRU eviction is triggered
- LFU (Least Frequently Used): Items with lowest access count are evicted first
- LRU (Least Recently Used): Among items with same access count, least recently accessed is evicted
- Creates snapshot file:
cache_baseline_max_entries_{max_entries}.txt - Example:
dotnet run --project ./CacheManager.Tester/CacheManager.Tester.csproj -- 10 1000
# Test with unlimited capacity (no eviction) - run operations 10 times
dotnet run --project ./CacheManager.Tester/CacheManager.Tester.csproj -- 10
# Test with max entries of 50 - run operations 10 times
dotnet run --project ./CacheManager.Tester/CacheManager.Tester.csproj -- 10 50
# Test with max entries of 100 - run operations 10 times
dotnet run --project ./CacheManager.Tester/CacheManager.Tester.csproj -- 10 100Arguments:
- First argument (optional): Number of iterations to run the operations (default: 1)
- Second argument (optional): Maximum cache entries for eviction testing (default: unlimited)
Each max entries setting creates its own baseline file, allowing you to test and compare behavior across different cache sizes.
Behavior:
- First run: creates
cache_baseline.txtfrom the current final cache contents and reports that a baseline snapshot was written. - Subsequent runs with the same
cache_input_operations.txt: prints a message indicating whether the behavior is consistent with the previous run and shows the elapsed time for the execution.
To run all three implementations (C#, Node.js, and Java) at once:
./test-all.shThe test-all.sh script supports the following parameters:
--max-entries N: Set maximum cache entries for eviction testing (default: unlimited)--iterations N: Set number of test iterations (default: 1)--help: Show help message with usage examples
# Run with unlimited cache (default behavior)
./test-all.sh
# Run with 1000 entry limit to test eviction behavior
./test-all.sh --max-entries 1000
# Run 5 iterations with 1000 entry limit
./test-all.sh --max-entries 1000 --iterations 5
# Show help and available options
./test-all.sh --help