From be4f6c19bce6ecab186720f5cbd76ab6d8a63a9b Mon Sep 17 00:00:00 2001 From: Murphy Tian Date: Mon, 24 Mar 2025 15:48:50 +0800 Subject: [PATCH 1/8] [Feat] Initialize js binding --- libCacheSim-node/binding.cc | 6 ++++++ libCacheSim-node/binding.gyp | 23 +++++++++++++++++++++++ libCacheSim-node/index.js | 8 ++++++++ libCacheSim-node/libCacheSim-node.md | 17 +++++++++++++++++ libCacheSim-node/package.json | 17 +++++++++++++++++ 5 files changed, 71 insertions(+) create mode 100644 libCacheSim-node/binding.cc create mode 100644 libCacheSim-node/binding.gyp create mode 100644 libCacheSim-node/index.js create mode 100644 libCacheSim-node/libCacheSim-node.md create mode 100644 libCacheSim-node/package.json diff --git a/libCacheSim-node/binding.cc b/libCacheSim-node/binding.cc new file mode 100644 index 00000000..779e7852 --- /dev/null +++ b/libCacheSim-node/binding.cc @@ -0,0 +1,6 @@ +#include +#include + +/* TODO: Create binding file */ + +NODE_API_MODULE(libcachesim, Init) \ No newline at end of file diff --git a/libCacheSim-node/binding.gyp b/libCacheSim-node/binding.gyp new file mode 100644 index 00000000..0f7c1afe --- /dev/null +++ b/libCacheSim-node/binding.gyp @@ -0,0 +1,23 @@ +{ + "targets": [ + { + "target_name": "libcachesim-addon", + "sources": [ "binding.cc" ], + "include_dirs": [ + " Date: Mon, 9 Jun 2025 18:16:55 +0800 Subject: [PATCH 2/8] [Feat] Add Node.js bindings for libCacheSim --- libCacheSim-node/.gitignore | 24 ++++ libCacheSim-node/README.md | 207 ++++++++++++++++++++++++++ libCacheSim-node/binding.cc | 263 +++++++++++++++++++++++++++++++++- libCacheSim-node/binding.gyp | 22 ++- libCacheSim-node/index.js | 66 ++++++++- libCacheSim-node/package.json | 23 ++- 6 files changed, 587 insertions(+), 18 deletions(-) create mode 100644 libCacheSim-node/.gitignore create mode 100644 libCacheSim-node/README.md diff --git a/libCacheSim-node/.gitignore b/libCacheSim-node/.gitignore new file mode 100644 index 00000000..b1f57179 --- /dev/null +++ b/libCacheSim-node/.gitignore @@ -0,0 +1,24 @@ +# Node.js dependencies +node_modules/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Build outputs +build/ +*.node + +# Package locks (optional for libraries) +package-lock.json + +# OS files +.DS_Store +Thumbs.db + +# IDE files +.vscode/ +.idea/ + +# Temporary files +*.tmp +*.log \ No newline at end of file diff --git a/libCacheSim-node/README.md b/libCacheSim-node/README.md new file mode 100644 index 00000000..ef056105 --- /dev/null +++ b/libCacheSim-node/README.md @@ -0,0 +1,207 @@ +# libCacheSim Node.js Bindings + +Node.js bindings for [libCacheSim](https://github.com/1a1a11a/libCacheSim), a high-performance cache simulator and analysis library. + +## Features + +- **High Performance**: Leverages the native libCacheSim C library for maximum performance +- **Multiple Cache Algorithms**: Support for LRU, FIFO, LFU, ARC, Clock, S3-FIFO, Sieve, and more +- **Multiple Trace Types**: Support for VSCSI, CSV, TXT, Binary, and Oracle trace formats +- **Detailed Results**: Returns comprehensive simulation statistics including hit/miss ratios +- **Easy to Use**: Simple JavaScript API with sensible defaults + +## Installation + +### Prerequisites + +Make sure you have the following dependencies installed: +- Node.js (version 14 or higher) +- glib-2.0 +- zstd +- cmake +- build-essential + +On Ubuntu/Debian: +```bash +sudo apt update +sudo apt install libglib2.0-dev libzstd-dev cmake build-essential +``` + +### Build and Install + +1. First, build libCacheSim with position-independent code: +```bash +cd .. # Go to libCacheSim root directory +rm -rf _build && mkdir _build && cd _build +cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON .. && make -j +``` + +2. Install Node.js dependencies and build the addon: +```bash +cd ../libCacheSim-node +npm install +npm run build +``` + +## Usage + +### Basic Example + +```javascript +const libCacheSim = require('./index'); + +// Run a simulation with default parameters +const result = libCacheSim.runSim(); +console.log(result); + +// Run a custom simulation +const customResult = libCacheSim.runSimulation( + '../data/trace.vscsi', // trace file path + 'vscsi', // trace type + 'lru', // cache algorithm + '10mb' // cache size +); +console.log(customResult); +``` + +### API Reference + +#### `runSimulation(tracePath, traceType, algorithm, cacheSize)` + +Run a cache simulation with custom parameters. + +**Parameters:** +- `tracePath` (string): Path to the trace file +- `traceType` (string): Type of trace file. Supported: `'vscsi'`, `'csv'`, `'txt'`, `'binary'`, `'oracle'` +- `algorithm` (string): Cache eviction algorithm. Supported: `'lru'`, `'fifo'`, `'lfu'`, `'arc'`, `'clock'`, `'s3fifo'`, `'sieve'` +- `cacheSize` (string): Cache size with unit. Examples: `'1mb'`, `'512kb'`, `'2gb'`, `'1024'` (bytes) + +**Returns:** +Object with simulation results: +```javascript +{ + totalRequests: 113872, // Total number of requests processed + hits: 15416, // Number of cache hits + misses: 98456, // Number of cache misses + hitRatio: 0.1354, // Cache hit ratio (0-1) + missRatio: 0.8646, // Cache miss ratio (0-1) + algorithm: 'lru', // Algorithm used + cacheSize: 1048576 // Cache size in bytes +} +``` + +#### `runSim()` + +Run a simulation with default parameters (backward compatibility). + +**Returns:** Same result object as `runSimulation()` + +#### `getSupportedAlgorithms()` + +Get list of supported cache algorithms. + +**Returns:** Array of algorithm names + +#### `getSupportedTraceTypes()` + +Get list of supported trace types. + +**Returns:** Array of trace type names + +### Examples + +#### Compare Different Algorithms + +```javascript +const libCacheSim = require('./index'); + +const algorithms = ['lru', 'fifo', 'lfu', 's3fifo']; +const tracePath = '../data/trace.vscsi'; +const cacheSize = '10mb'; + +algorithms.forEach(algo => { + const result = libCacheSim.runSimulation(tracePath, 'vscsi', algo, cacheSize); + console.log(`${algo.toUpperCase()}: Hit Ratio = ${result.hitRatio.toFixed(4)}`); +}); +``` + +#### Analyze Different Cache Sizes + +```javascript +const libCacheSim = require('./index'); + +const cacheSizes = ['1mb', '5mb', '10mb', '50mb', '100mb']; +const tracePath = '../data/trace.vscsi'; + +cacheSizes.forEach(size => { + const result = libCacheSim.runSimulation(tracePath, 'vscsi', 'lru', size); + console.log(`Size ${size}: Hit Ratio = ${result.hitRatio.toFixed(4)}`); +}); +``` + +## Supported Cache Algorithms + +- **LRU** (Least Recently Used) +- **FIFO** (First In, First Out) +- **LFU** (Least Frequently Used) +- **ARC** (Adaptive Replacement Cache) +- **Clock** (Clock algorithm) +- **S3-FIFO** (Static-Dynamic-Static FIFO) +- **Sieve** (Sieve eviction algorithm) + +## Supported Trace Types + +- **VSCSI**: Virtual SCSI trace format +- **CSV**: Comma-separated values +- **TXT**: Plain text format +- **Binary**: Binary trace format +- **Oracle**: Oracle general trace format + +## Error Handling + +The library throws JavaScript errors for common issues: + +```javascript +try { + const result = libCacheSim.runSimulation('/invalid/path', 'vscsi', 'lru', '1mb'); +} catch (error) { + console.error('Simulation failed:', error.message); +} +``` + +## Performance Notes + +- The native C library provides excellent performance for large trace files +- For optimal performance, use binary trace formats when possible +- Large cache sizes may require significant memory + +## Development + +### Building from Source + +```bash +# Clean build +npm run clean +npm run build + +# Development build with debugging +DEBUG=1 npm run build +``` + +### Running Tests + +```bash +node index.js # Runs example simulations +``` + +## License + +This project follows the same license as libCacheSim. See the main project repository for details. + +## Contributing + +Please submit issues and pull requests to the main libCacheSim repository. + +## Related + +- [libCacheSim](https://github.com/1a1a11a/libCacheSim) - Main library \ No newline at end of file diff --git a/libCacheSim-node/binding.cc b/libCacheSim-node/binding.cc index 779e7852..49ba34d2 100644 --- a/libCacheSim-node/binding.cc +++ b/libCacheSim-node/binding.cc @@ -1,6 +1,263 @@ #include -#include +#include "libCacheSim.h" +#include +#include +#include +#include +#include +#include -/* TODO: Create binding file */ +// Helper function to check if file exists +bool fileExists(const std::string& filename) { + struct stat buffer; + return (stat(filename.c_str(), &buffer) == 0); +} -NODE_API_MODULE(libcachesim, Init) \ No newline at end of file +// Helper function to parse cache size string (e.g., "1mb", "1gb", "1024") +uint64_t parseCacheSize(const std::string& sizeStr) { + if (sizeStr.empty()) return 0; + + std::string lower = sizeStr; + std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower); + + // Extract number and unit + size_t pos = 0; + while (pos < lower.length() && (isdigit(lower[pos]) || lower[pos] == '.')) { + pos++; + } + + double value = std::stod(lower.substr(0, pos)); + std::string unit = lower.substr(pos); + + uint64_t multiplier = 1; + if (unit == "kb" || unit == "k") multiplier = 1024; + else if (unit == "mb" || unit == "m") multiplier = 1024 * 1024; + else if (unit == "gb" || unit == "g") multiplier = 1024 * 1024 * 1024; + else if (unit == "tb" || unit == "t") multiplier = 1024ULL * 1024 * 1024 * 1024; + + return (uint64_t)(value * multiplier); +} + +// Helper function to get cache constructor by algorithm name +cache_t* createCache(const std::string& algo, const common_cache_params_t& params) { + std::string lowerAlgo = algo; + std::transform(lowerAlgo.begin(), lowerAlgo.end(), lowerAlgo.begin(), ::tolower); + + if (lowerAlgo == "lru") return LRU_init(params, nullptr); + else if (lowerAlgo == "fifo") return FIFO_init(params, nullptr); + else if (lowerAlgo == "lfu") return LFU_init(params, nullptr); + else if (lowerAlgo == "arc") return ARC_init(params, nullptr); + else if (lowerAlgo == "clock") return Clock_init(params, nullptr); + else if (lowerAlgo == "s3fifo") return S3FIFO_init(params, nullptr); + else if (lowerAlgo == "sieve") return Sieve_init(params, nullptr); + + return nullptr; // Unknown algorithm +} + +// Main simulation function +Napi::Value runSimulation(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + + // Check arguments + if (info.Length() < 3) { + Napi::TypeError::New(env, "Expected at least 3 arguments: tracePath, traceType, algorithm").ThrowAsJavaScriptException(); + return env.Null(); + } + + if (!info[0].IsString() || !info[1].IsString() || !info[2].IsString()) { + Napi::TypeError::New(env, "First three arguments must be strings").ThrowAsJavaScriptException(); + return env.Null(); + } + + std::string tracePath = info[0].As().Utf8Value(); + std::string traceType = info[1].As().Utf8Value(); + std::string algorithm = info[2].As().Utf8Value(); + + // Check if file exists before trying to open it + if (!fileExists(tracePath)) { + Napi::Error::New(env, "Trace file does not exist: " + tracePath).ThrowAsJavaScriptException(); + return env.Null(); + } + + // Parse optional cache size (default 1MB) + uint64_t cacheSize = 1024 * 1024; // 1MB default + if (info.Length() > 3 && info[3].IsString()) { + try { + cacheSize = parseCacheSize(info[3].As().Utf8Value()); + if (cacheSize == 0) { + Napi::Error::New(env, "Invalid cache size").ThrowAsJavaScriptException(); + return env.Null(); + } + } catch (const std::exception& e) { + Napi::Error::New(env, "Invalid cache size format").ThrowAsJavaScriptException(); + return env.Null(); + } + } + + // Determine trace type enum + trace_type_e trace_type_enum; + std::string lowerTraceType = traceType; + std::transform(lowerTraceType.begin(), lowerTraceType.end(), lowerTraceType.begin(), ::tolower); + + if (lowerTraceType == "vscsi") trace_type_enum = VSCSI_TRACE; + else if (lowerTraceType == "csv") trace_type_enum = CSV_TRACE; + else if (lowerTraceType == "txt" || lowerTraceType == "plain_txt") trace_type_enum = PLAIN_TXT_TRACE; + else if (lowerTraceType == "binary" || lowerTraceType == "bin") trace_type_enum = BIN_TRACE; + else if (lowerTraceType == "oracle") trace_type_enum = ORACLE_GENERAL_TRACE; + else { + Napi::Error::New(env, "Unsupported trace type. Supported: vscsi, csv, txt, binary, oracle").ThrowAsJavaScriptException(); + return env.Null(); + } + + // Validate algorithm before creating cache + std::string lowerAlgo = algorithm; + std::transform(lowerAlgo.begin(), lowerAlgo.end(), lowerAlgo.begin(), ::tolower); + if (lowerAlgo != "lru" && lowerAlgo != "fifo" && lowerAlgo != "lfu" && + lowerAlgo != "arc" && lowerAlgo != "clock" && lowerAlgo != "s3fifo" && lowerAlgo != "sieve") { + Napi::Error::New(env, "Unsupported algorithm. Supported: lru, fifo, lfu, arc, clock, s3fifo, sieve").ThrowAsJavaScriptException(); + return env.Null(); + } + + // Open the trace file + reader_t* reader = open_trace(tracePath.c_str(), trace_type_enum, nullptr); + if (!reader) { + Napi::Error::New(env, "Failed to open trace file: " + tracePath).ThrowAsJavaScriptException(); + return env.Null(); + } + + // Create a request container + request_t* req = new_request(); + if (!req) { + close_trace(reader); + Napi::Error::New(env, "Failed to allocate request").ThrowAsJavaScriptException(); + return env.Null(); + } + + // Initialize cache + common_cache_params_t cc_params = { + .cache_size = cacheSize, + .default_ttl = 0, + .hashpower = 24, + .consider_obj_metadata = false + }; + + cache_t* cache = createCache(algorithm, cc_params); + if (!cache) { + close_trace(reader); + free_request(req); + Napi::Error::New(env, "Failed to create cache with algorithm: " + algorithm).ThrowAsJavaScriptException(); + return env.Null(); + } + + // Run simulation loop + uint64_t n_req = 0; + uint64_t n_miss = 0; + uint64_t n_hit = 0; + + while (read_one_req(reader, req) == 0) { + bool hit = cache->get(cache, req); + if (hit) n_hit++; + else n_miss++; + n_req++; + } + + // Cleanup + close_trace(reader); + free_request(req); + cache->cache_free(cache); + + // Return simulation results as object + Napi::Object result = Napi::Object::New(env); + result.Set("totalRequests", Napi::Number::New(env, n_req)); + result.Set("hits", Napi::Number::New(env, n_hit)); + result.Set("misses", Napi::Number::New(env, n_miss)); + result.Set("hitRatio", Napi::Number::New(env, n_req > 0 ? (double)n_hit / n_req : 0.0)); + result.Set("missRatio", Napi::Number::New(env, n_req > 0 ? (double)n_miss / n_req : 0.0)); + result.Set("algorithm", Napi::String::New(env, algorithm)); + result.Set("cacheSize", Napi::Number::New(env, cacheSize)); + + return result; +} + +// Simple simulation with hardcoded values (backward compatibility) +Napi::Value runSim(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + + // Check if the default trace file exists + if (!fileExists("../data/cloudPhysicsIO.vscsi")) { + Napi::Error::New(env, "Default trace file not found: ../data/cloudPhysicsIO.vscsi").ThrowAsJavaScriptException(); + return env.Null(); + } + + // === Open the trace file === + reader_t* reader = open_trace( + "../data/cloudPhysicsIO.vscsi", + VSCSI_TRACE, + nullptr // No special initialization parameters + ); + + if (!reader) { + Napi::Error::New(env, "Failed to open trace").ThrowAsJavaScriptException(); + return env.Null(); + } + + // === Create a request container === + request_t* req = new_request(); + if (!req) { + close_trace(reader); + Napi::Error::New(env, "Failed to allocate request").ThrowAsJavaScriptException(); + return env.Null(); + } + + // === Initialize an LRU cache === + common_cache_params_t cc_params = { + .cache_size = 1024 * 1024, // 1MB + .default_ttl = 0, + .hashpower = 24, + .consider_obj_metadata = false + }; + cache_t* cache = LRU_init(cc_params, nullptr); + if (!cache) { + close_trace(reader); + free_request(req); + Napi::Error::New(env, "Failed to create cache").ThrowAsJavaScriptException(); + return env.Null(); + } + + // === Run simulation loop === + uint64_t n_req = 0; + uint64_t n_miss = 0; + uint64_t n_hit = 0; + while (read_one_req(reader, req) == 0) { + bool hit = cache->get(cache, req); + if (hit) n_hit++; + else n_miss++; + n_req++; + } + + // === Cleanup === + close_trace(reader); + free_request(req); + cache->cache_free(cache); + + // === Return results as object === + Napi::Object result = Napi::Object::New(env); + result.Set("totalRequests", Napi::Number::New(env, n_req)); + result.Set("hits", Napi::Number::New(env, n_hit)); + result.Set("misses", Napi::Number::New(env, n_miss)); + result.Set("hitRatio", Napi::Number::New(env, n_req > 0 ? (double)n_hit / n_req : 0.0)); + result.Set("missRatio", Napi::Number::New(env, n_req > 0 ? (double)n_miss / n_req : 0.0)); + result.Set("algorithm", Napi::String::New(env, "lru")); + result.Set("cacheSize", Napi::Number::New(env, 1024 * 1024)); + + return result; +} + +// Node.js addon initialization +Napi::Object Init(Napi::Env env, Napi::Object exports) { + exports.Set("runSim", Napi::Function::New(env, runSim)); + exports.Set("runSimulation", Napi::Function::New(env, runSimulation)); + return exports; +} + +NODE_API_MODULE(libcachesim_addon, Init) diff --git a/libCacheSim-node/binding.gyp b/libCacheSim-node/binding.gyp index 0f7c1afe..dce224b6 100644 --- a/libCacheSim-node/binding.gyp +++ b/libCacheSim-node/binding.gyp @@ -1,23 +1,31 @@ { "targets": [ { - "target_name": "libcachesim-addon", + "target_name": "cachesim-addon", "sources": [ "binding.cc" ], "include_dirs": [ "=14.0.0" + }, "dependencies": { "node-addon-api": "^8.3.1" - } + }, + "devDependencies": {}, + "files": [ + "index.js", + "binding.cc", + "binding.gyp", + "README.md", + "test.js" + ] } From 5393f695f26553317c86292b91620a29ef6358fb Mon Sep 17 00:00:00 2001 From: Murphy Tian Date: Thu, 12 Jun 2025 21:02:27 +0800 Subject: [PATCH 3/8] [Fix] fPIC error in building js binding --- libCacheSim-node/binding.gyp | 2 ++ libCacheSim-node/package.json | 25 +++++++++++++++++-------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/libCacheSim-node/binding.gyp b/libCacheSim-node/binding.gyp index dce224b6..c89f1dd7 100644 --- a/libCacheSim-node/binding.gyp +++ b/libCacheSim-node/binding.gyp @@ -20,6 +20,8 @@ ], "cflags!": [ "-fno-exceptions" ], "cflags_cc!": [ "-fno-exceptions" ], + "cflags": [ "-fPIC" ], + "cflags_cc": [ "-fPIC" ], "defines": [ "NAPI_DISABLE_CPP_EXCEPTIONS" ], "ldflags": [ "-Wl,--whole-archive", diff --git a/libCacheSim-node/package.json b/libCacheSim-node/package.json index 2d678fac..4b06ed03 100644 --- a/libCacheSim-node/package.json +++ b/libCacheSim-node/package.json @@ -3,20 +3,27 @@ "version": "1.0.0", "main": "index.js", "scripts": { - "install": "node-gyp configure build", - "build": "node-gyp rebuild", + "prebuild": "npm run ensure-libcachesim", + "ensure-libcachesim": "cd .. && if [ ! -f '_build/liblibCacheSim.a' ]; then rm -rf _build && mkdir _build && cd _build && cmake .. && make -j; else echo 'libCacheSim already exists'; fi", + "install": "npm run build", + "build": "CFLAGS=-fPIC CXXFLAGS=-fPIC node-gyp rebuild", "clean": "node-gyp clean", "test": "node test.js", - "examples": "node examples.js" + "examples": "node examples.js", + "prepack": "npm run build" }, - "keywords": ["cache", "simulation", "performance", "lru", "fifo", "s3fifo", "sieve"], + "keywords": ["cache", "simulation", "performance", "lru", "fifo", "s3fifo", "sieve", "libcachesim"], "author": "Murphy Tian", "license": "MIT", - "description": "Node.js bindings for libCacheSim - A high-performance cache simulator and analysis library", + "description": "Node.js bindings for libCacheSim - A high-performance cache simulator and analysis library supporting LRU, FIFO, S3-FIFO, Sieve and other caching algorithms", "repository": { "type": "git", "url": "https://github.com/1a1a11a/libCacheSim" }, + "homepage": "https://github.com/1a1a11a/libCacheSim/tree/develop/libCacheSim-node", + "bugs": { + "url": "https://github.com/1a1a11a/libCacheSim/issues" + }, "engines": { "node": ">=14.0.0" }, @@ -28,7 +35,9 @@ "index.js", "binding.cc", "binding.gyp", - "README.md", - "test.js" - ] + "README.md" + ], + "publishConfig": { + "registry": "https://registry.npmjs.org/" + } } From dac5f3cbae7575cb801ffce77d96044cc1cdc0dc Mon Sep 17 00:00:00 2001 From: Murphy Tian Date: Thu, 12 Jun 2025 22:34:47 +0800 Subject: [PATCH 4/8] [Refactor] README.md to libCacheSim-node.md --- libCacheSim-node/README.md | 207 --------------------------- libCacheSim-node/libCacheSim-node.md | 124 +++++++++++++++- libCacheSim-node/package.json | 4 +- 3 files changed, 125 insertions(+), 210 deletions(-) delete mode 100644 libCacheSim-node/README.md diff --git a/libCacheSim-node/README.md b/libCacheSim-node/README.md deleted file mode 100644 index ef056105..00000000 --- a/libCacheSim-node/README.md +++ /dev/null @@ -1,207 +0,0 @@ -# libCacheSim Node.js Bindings - -Node.js bindings for [libCacheSim](https://github.com/1a1a11a/libCacheSim), a high-performance cache simulator and analysis library. - -## Features - -- **High Performance**: Leverages the native libCacheSim C library for maximum performance -- **Multiple Cache Algorithms**: Support for LRU, FIFO, LFU, ARC, Clock, S3-FIFO, Sieve, and more -- **Multiple Trace Types**: Support for VSCSI, CSV, TXT, Binary, and Oracle trace formats -- **Detailed Results**: Returns comprehensive simulation statistics including hit/miss ratios -- **Easy to Use**: Simple JavaScript API with sensible defaults - -## Installation - -### Prerequisites - -Make sure you have the following dependencies installed: -- Node.js (version 14 or higher) -- glib-2.0 -- zstd -- cmake -- build-essential - -On Ubuntu/Debian: -```bash -sudo apt update -sudo apt install libglib2.0-dev libzstd-dev cmake build-essential -``` - -### Build and Install - -1. First, build libCacheSim with position-independent code: -```bash -cd .. # Go to libCacheSim root directory -rm -rf _build && mkdir _build && cd _build -cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON .. && make -j -``` - -2. Install Node.js dependencies and build the addon: -```bash -cd ../libCacheSim-node -npm install -npm run build -``` - -## Usage - -### Basic Example - -```javascript -const libCacheSim = require('./index'); - -// Run a simulation with default parameters -const result = libCacheSim.runSim(); -console.log(result); - -// Run a custom simulation -const customResult = libCacheSim.runSimulation( - '../data/trace.vscsi', // trace file path - 'vscsi', // trace type - 'lru', // cache algorithm - '10mb' // cache size -); -console.log(customResult); -``` - -### API Reference - -#### `runSimulation(tracePath, traceType, algorithm, cacheSize)` - -Run a cache simulation with custom parameters. - -**Parameters:** -- `tracePath` (string): Path to the trace file -- `traceType` (string): Type of trace file. Supported: `'vscsi'`, `'csv'`, `'txt'`, `'binary'`, `'oracle'` -- `algorithm` (string): Cache eviction algorithm. Supported: `'lru'`, `'fifo'`, `'lfu'`, `'arc'`, `'clock'`, `'s3fifo'`, `'sieve'` -- `cacheSize` (string): Cache size with unit. Examples: `'1mb'`, `'512kb'`, `'2gb'`, `'1024'` (bytes) - -**Returns:** -Object with simulation results: -```javascript -{ - totalRequests: 113872, // Total number of requests processed - hits: 15416, // Number of cache hits - misses: 98456, // Number of cache misses - hitRatio: 0.1354, // Cache hit ratio (0-1) - missRatio: 0.8646, // Cache miss ratio (0-1) - algorithm: 'lru', // Algorithm used - cacheSize: 1048576 // Cache size in bytes -} -``` - -#### `runSim()` - -Run a simulation with default parameters (backward compatibility). - -**Returns:** Same result object as `runSimulation()` - -#### `getSupportedAlgorithms()` - -Get list of supported cache algorithms. - -**Returns:** Array of algorithm names - -#### `getSupportedTraceTypes()` - -Get list of supported trace types. - -**Returns:** Array of trace type names - -### Examples - -#### Compare Different Algorithms - -```javascript -const libCacheSim = require('./index'); - -const algorithms = ['lru', 'fifo', 'lfu', 's3fifo']; -const tracePath = '../data/trace.vscsi'; -const cacheSize = '10mb'; - -algorithms.forEach(algo => { - const result = libCacheSim.runSimulation(tracePath, 'vscsi', algo, cacheSize); - console.log(`${algo.toUpperCase()}: Hit Ratio = ${result.hitRatio.toFixed(4)}`); -}); -``` - -#### Analyze Different Cache Sizes - -```javascript -const libCacheSim = require('./index'); - -const cacheSizes = ['1mb', '5mb', '10mb', '50mb', '100mb']; -const tracePath = '../data/trace.vscsi'; - -cacheSizes.forEach(size => { - const result = libCacheSim.runSimulation(tracePath, 'vscsi', 'lru', size); - console.log(`Size ${size}: Hit Ratio = ${result.hitRatio.toFixed(4)}`); -}); -``` - -## Supported Cache Algorithms - -- **LRU** (Least Recently Used) -- **FIFO** (First In, First Out) -- **LFU** (Least Frequently Used) -- **ARC** (Adaptive Replacement Cache) -- **Clock** (Clock algorithm) -- **S3-FIFO** (Static-Dynamic-Static FIFO) -- **Sieve** (Sieve eviction algorithm) - -## Supported Trace Types - -- **VSCSI**: Virtual SCSI trace format -- **CSV**: Comma-separated values -- **TXT**: Plain text format -- **Binary**: Binary trace format -- **Oracle**: Oracle general trace format - -## Error Handling - -The library throws JavaScript errors for common issues: - -```javascript -try { - const result = libCacheSim.runSimulation('/invalid/path', 'vscsi', 'lru', '1mb'); -} catch (error) { - console.error('Simulation failed:', error.message); -} -``` - -## Performance Notes - -- The native C library provides excellent performance for large trace files -- For optimal performance, use binary trace formats when possible -- Large cache sizes may require significant memory - -## Development - -### Building from Source - -```bash -# Clean build -npm run clean -npm run build - -# Development build with debugging -DEBUG=1 npm run build -``` - -### Running Tests - -```bash -node index.js # Runs example simulations -``` - -## License - -This project follows the same license as libCacheSim. See the main project repository for details. - -## Contributing - -Please submit issues and pull requests to the main libCacheSim repository. - -## Related - -- [libCacheSim](https://github.com/1a1a11a/libCacheSim) - Main library \ No newline at end of file diff --git a/libCacheSim-node/libCacheSim-node.md b/libCacheSim-node/libCacheSim-node.md index b85f90c1..ad7340cb 100644 --- a/libCacheSim-node/libCacheSim-node.md +++ b/libCacheSim-node/libCacheSim-node.md @@ -9,9 +9,131 @@ Node.js bindings for libCacheSim. cd libCacheSim-node npm install -g node-gyp npm install +npm run build ``` ## Usage + +### Basic Example + +```javascript +const libCacheSim = require('./index'); + +// Run a simulation with default parameters +const result = libCacheSim.runSim(); +console.log(result); + +// Run a custom simulation +const customResult = libCacheSim.runSimulation( + '../data/trace.vscsi', // trace file path + 'vscsi', // trace type + 'lru', // cache algorithm + '10mb' // cache size +); +console.log(customResult); +``` + +### API Reference + +#### `runSimulation(tracePath, traceType, algorithm, cacheSize)` + +Run a cache simulation with custom parameters. + +**Parameters:** +- `tracePath` (string): Path to the trace file +- `traceType` (string): Type of trace file. Supported: `'vscsi'`, `'csv'`, `'txt'`, `'binary'`, `'oracle'` +- `algorithm` (string): Cache eviction algorithm. Supported: `'lru'`, `'fifo'`, `'lfu'`, `'arc'`, `'clock'`, `'s3fifo'`, `'sieve'` +- `cacheSize` (string): Cache size with unit. Examples: `'1mb'`, `'512kb'`, `'2gb'`, `'1024'` (bytes) + +**Returns:** +Object with simulation results: +```javascript +{ + totalRequests: 113872, // Total number of requests processed + hits: 15416, // Number of cache hits + misses: 98456, // Number of cache misses + hitRatio: 0.1354, // Cache hit ratio (0-1) + missRatio: 0.8646, // Cache miss ratio (0-1) + algorithm: 'lru', // Algorithm used + cacheSize: 1048576 // Cache size in bytes +} +``` + +#### `runSim()` + +Run a simulation with default parameters (backward compatibility). + +**Returns:** Same result object as `runSimulation()` + +#### `getSupportedAlgorithms()` + +Get list of supported cache algorithms. + +**Returns:** Array of algorithm names + +#### `getSupportedTraceTypes()` + +Get list of supported trace types. + +**Returns:** Array of trace type names + +### Examples + +#### Compare Different Algorithms + +```javascript +const libCacheSim = require('./index'); + +const algorithms = ['lru', 'fifo', 'lfu', 's3fifo']; +const tracePath = '../data/trace.vscsi'; +const cacheSize = '10mb'; + +algorithms.forEach(algo => { + const result = libCacheSim.runSimulation(tracePath, 'vscsi', algo, cacheSize); + console.log(`${algo.toUpperCase()}: Hit Ratio = ${result.hitRatio.toFixed(4)}`); +}); +``` + +#### Analyze Different Cache Sizes + +```javascript +const libCacheSim = require('./index'); + +const cacheSizes = ['1mb', '5mb', '10mb', '50mb', '100mb']; +const tracePath = '../data/trace.vscsi'; + +cacheSizes.forEach(size => { + const result = libCacheSim.runSimulation(tracePath, 'vscsi', 'lru', size); + console.log(`Size ${size}: Hit Ratio = ${result.hitRatio.toFixed(4)}`); +}); +``` + +### Error Handling + +The library throws JavaScript errors for common issues: + +```javascript +try { + const result = libCacheSim.runSimulation('/invalid/path', 'vscsi', 'lru', '1mb'); +} catch (error) { + console.error('Simulation failed:', error.message); +} +``` +## Development + +### Building from Source + ```bash -node index.js +# Clean build +npm run clean +npm run build + +# Development build with debugging +DEBUG=1 npm run build ``` + +### Running Tests + +```bash +node index.js # Runs example simulations +``` \ No newline at end of file diff --git a/libCacheSim-node/package.json b/libCacheSim-node/package.json index 4b06ed03..95d6f198 100644 --- a/libCacheSim-node/package.json +++ b/libCacheSim-node/package.json @@ -4,10 +4,10 @@ "main": "index.js", "scripts": { "prebuild": "npm run ensure-libcachesim", - "ensure-libcachesim": "cd .. && if [ ! -f '_build/liblibCacheSim.a' ]; then rm -rf _build && mkdir _build && cd _build && cmake .. && make -j; else echo 'libCacheSim already exists'; fi", + "ensure-libcachesim": "cd .. && rm -rf _build && mkdir _build && cd _build && cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON .. && make -j", "install": "npm run build", "build": "CFLAGS=-fPIC CXXFLAGS=-fPIC node-gyp rebuild", - "clean": "node-gyp clean", + "clean": "node-gyp clean && cd .. && rm -rf _build", "test": "node test.js", "examples": "node examples.js", "prepack": "npm run build" From eef29ace81ec2ea838d3ccad4e8f8abe4868e4c8 Mon Sep 17 00:00:00 2001 From: Murphy Tian Date: Sat, 14 Jun 2025 15:56:13 +0800 Subject: [PATCH 5/8] [Feat] Support libcachesim-cli global installation --- libCacheSim-node/cli.js | 129 +++++++++++++++++++++++++++ libCacheSim-node/libCacheSim-node.md | 58 ++++++++++++ 2 files changed, 187 insertions(+) create mode 100755 libCacheSim-node/cli.js diff --git a/libCacheSim-node/cli.js b/libCacheSim-node/cli.js new file mode 100755 index 00000000..67106f17 --- /dev/null +++ b/libCacheSim-node/cli.js @@ -0,0 +1,129 @@ +#!/usr/bin/env node + +const libCacheSim = require('./index'); +const path = require('path'); + +// Simple command line argument parser +function parseArgs() { + const args = process.argv.slice(2); + const options = { + trace: null, + type: null, + algorithm: null, + size: null, + help: false + }; + + for (let i = 0; i < args.length; i++) { + switch (args[i]) { + case '--trace': + case '-t': + options.trace = args[++i]; + break; + case '--type': + options.type = args[++i]; + break; + case '--algorithm': + case '-a': + options.algorithm = args[++i]; + break; + case '--size': + case '-s': + options.size = args[++i]; + break; + case '--help': + case '-h': + options.help = true; + break; + default: + console.error(`Unknown option: ${args[i]}`); + process.exit(1); + } + } + + return options; +} + +function showHelp() { + console.log(` +libcachesim-node CLI + +Usage: + libcachesim-cli --trace --type --algorithm --size + +Options: + --trace, -t Path to trace file (required) + --type Trace type (required) + Supported: ${libCacheSim.getSupportedTraceTypes().join(', ')} + --algorithm, -a Cache algorithm (required) + Supported: ${libCacheSim.getSupportedAlgorithms().join(', ')} + --size, -s Cache size (required) + Examples: 1mb, 512kb, 2gb, 1024 (bytes) + --help, -h Show this help message + +Examples: + libcachesim-cli -t trace.vscsi --type vscsi -a lru -s 10mb + libcachesim-cli --trace data.csv --type csv --algorithm s3fifo --size 50mb +`); +} + +function main() { + const options = parseArgs(); + + if (options.help) { + showHelp(); + return; + } + + // Check that all required parameters are provided + if (!options.trace || !options.type || !options.algorithm || !options.size) { + console.error('Error: All parameters are required.'); + console.error('Missing:'); + if (!options.trace) console.error(' --trace '); + if (!options.type) console.error(' --type '); + if (!options.algorithm) console.error(' --algorithm '); + if (!options.size) console.error(' --size '); + console.error('\nUse --help for usage information.'); + process.exit(1); + } + + try { + // Check if trace file exists + const fs = require('fs'); + if (!fs.existsSync(options.trace)) { + console.error(`Error: Trace file '${options.trace}' not found.`); + process.exit(1); + } + + console.log(`Running simulation with trace: ${options.trace}`); + console.log(`Algorithm: ${options.algorithm}, Size: ${options.size}, Type: ${options.type}`); + + // Run simulation + const result = libCacheSim.runSimulation( + options.trace, + options.type, + options.algorithm, + options.size + ); + + // Display results + console.log('\n=== Cache Simulation Results ==='); + console.log(`Algorithm: ${result.algorithm}`); + console.log(`Cache Size: ${(result.cacheSize / (1024 * 1024)).toFixed(2)} MB`); + console.log(`Total Requests: ${result.totalRequests.toLocaleString()}`); + console.log(`Cache Hits: ${result.hits.toLocaleString()}`); + console.log(`Cache Misses: ${result.misses.toLocaleString()}`); + console.log(`Hit Ratio: ${(result.hitRatio * 100).toFixed(2)}%`); + console.log(`Miss Ratio: ${(result.missRatio * 100).toFixed(2)}%`); + + } catch (error) { + console.error('Error running simulation:', error.message); + process.exit(1); + } +} + +if (require.main === module) { + main(); +} + +module.exports = { parseArgs, showHelp, main }; \ No newline at end of file diff --git a/libCacheSim-node/libCacheSim-node.md b/libCacheSim-node/libCacheSim-node.md index ad7340cb..cd722523 100644 --- a/libCacheSim-node/libCacheSim-node.md +++ b/libCacheSim-node/libCacheSim-node.md @@ -5,6 +5,8 @@ Node.js bindings for libCacheSim. ## Installation +### Local Installation (Development) + ```bash cd libCacheSim-node npm install -g node-gyp @@ -12,6 +14,31 @@ npm install npm run build ``` +### Global Installation + +To install libcachesim-node globally and make the CLI available system-wide: + +```bash +cd libCacheSim-node +npm install -g . +``` + +After global installation, you can use the CLI from any directory: + +```bash +libcachesim-cli --help +libcachesim-cli --trace /path/to/trace.vscsi --algorithm lru --size 10mb +``` + +**Note:** Global installation requires the libCacheSim C++ library to be built first. Make sure you have: +- CMake installed +- A C++ compiler (gcc/clang) +- The parent libCacheSim repository properly built + +If you encounter build issues during global installation, you can: +1. First build locally: `npm run build` +2. Then install globally: `npm install -g .` + ## Usage ### Basic Example @@ -119,6 +146,37 @@ try { console.error('Simulation failed:', error.message); } ``` + +## Command Line Interface + +After global installation, you can use the `libcachesim-cli` command: + +### CLI Usage + +```bash +libcachesim-cli [options] +``` + +### CLI Options + +- `--trace, -t `: Path to trace file (required) +- `--type `: Trace type (required) +- `--algorithm, -a `: Cache algorithm (required) +- `--size, -s `: Cache size (required) +- `--help, -h`: Show help message + +### CLI Examples + +```bash +# Basic simulation +libcachesim-cli -t trace.vscsi --type vscsi -a lru -s 10mb + +# Compare S3-FIFO with larger cache +libcachesim-cli --trace data.csv --type csv --algorithm s3fifo --size 50mb + +# Show help +libcachesim-cli --help +``` ## Development ### Building from Source From 7b4967eca99df8c6399a74b331835eab0fa5607c Mon Sep 17 00:00:00 2001 From: Murphy Tian Date: Sat, 14 Jun 2025 15:57:18 +0800 Subject: [PATCH 6/8] update package.json --- libCacheSim-node/package.json | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libCacheSim-node/package.json b/libCacheSim-node/package.json index 95d6f198..99009a88 100644 --- a/libCacheSim-node/package.json +++ b/libCacheSim-node/package.json @@ -2,9 +2,12 @@ "name": "libcachesim-node", "version": "1.0.0", "main": "index.js", + "bin": { + "libcachesim-cli": "./cli.js" + }, "scripts": { "prebuild": "npm run ensure-libcachesim", - "ensure-libcachesim": "cd .. && rm -rf _build && mkdir _build && cd _build && cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON .. && make -j", + "ensure-libcachesim": "cd .. && rm -rf _build && mkdir _build && cd _build && cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Debug .. && make -j", "install": "npm run build", "build": "CFLAGS=-fPIC CXXFLAGS=-fPIC node-gyp rebuild", "clean": "node-gyp clean && cd .. && rm -rf _build", @@ -33,6 +36,7 @@ "devDependencies": {}, "files": [ "index.js", + "cli.js", "binding.cc", "binding.gyp", "README.md" @@ -40,4 +44,4 @@ "publishConfig": { "registry": "https://registry.npmjs.org/" } -} +} \ No newline at end of file From 9229af29b744d76479250b8554b4d84f5878954a Mon Sep 17 00:00:00 2001 From: Murphy Tian Date: Sat, 14 Jun 2025 16:22:41 +0800 Subject: [PATCH 7/8] [Feat] add test.js, update package.json and libCacheSim-node.md --- libCacheSim-node/libCacheSim-node.md | 9 +- libCacheSim-node/package.json | 16 ++- libCacheSim-node/test.js | 192 +++++++++++++++++++++++++++ 3 files changed, 209 insertions(+), 8 deletions(-) create mode 100644 libCacheSim-node/test.js diff --git a/libCacheSim-node/libCacheSim-node.md b/libCacheSim-node/libCacheSim-node.md index cd722523..91de5f3e 100644 --- a/libCacheSim-node/libCacheSim-node.md +++ b/libCacheSim-node/libCacheSim-node.md @@ -27,7 +27,7 @@ After global installation, you can use the CLI from any directory: ```bash libcachesim-cli --help -libcachesim-cli --trace /path/to/trace.vscsi --algorithm lru --size 10mb +libcachesim-cli --trace /path/to/trace.vscsi --type vscsi --algorithm lru --size 10mb ``` **Note:** Global installation requires the libCacheSim C++ library to be built first. Make sure you have: @@ -154,7 +154,7 @@ After global installation, you can use the `libcachesim-cli` command: ### CLI Usage ```bash -libcachesim-cli [options] +libcachesim-cli --trace --type --algorithm --size ``` ### CLI Options @@ -186,12 +186,13 @@ libcachesim-cli --help npm run clean npm run build -# Development build with debugging +# Debug build with debugging symbols DEBUG=1 npm run build ``` ### Running Tests ```bash -node index.js # Runs example simulations +# Run test suite +npm test ``` \ No newline at end of file diff --git a/libCacheSim-node/package.json b/libCacheSim-node/package.json index 99009a88..906ed037 100644 --- a/libCacheSim-node/package.json +++ b/libCacheSim-node/package.json @@ -7,15 +7,23 @@ }, "scripts": { "prebuild": "npm run ensure-libcachesim", - "ensure-libcachesim": "cd .. && rm -rf _build && mkdir _build && cd _build && cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Debug .. && make -j", + "ensure-libcachesim": "cd .. && rm -rf _build && mkdir _build && cd _build && cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=${DEBUG:+Debug}${DEBUG:-Release} .. && make -j", "install": "npm run build", "build": "CFLAGS=-fPIC CXXFLAGS=-fPIC node-gyp rebuild", "clean": "node-gyp clean && cd .. && rm -rf _build", "test": "node test.js", - "examples": "node examples.js", "prepack": "npm run build" }, - "keywords": ["cache", "simulation", "performance", "lru", "fifo", "s3fifo", "sieve", "libcachesim"], + "keywords": [ + "cache", + "simulation", + "performance", + "lru", + "fifo", + "s3fifo", + "sieve", + "libcachesim" + ], "author": "Murphy Tian", "license": "MIT", "description": "Node.js bindings for libCacheSim - A high-performance cache simulator and analysis library supporting LRU, FIFO, S3-FIFO, Sieve and other caching algorithms", @@ -44,4 +52,4 @@ "publishConfig": { "registry": "https://registry.npmjs.org/" } -} \ No newline at end of file +} diff --git a/libCacheSim-node/test.js b/libCacheSim-node/test.js new file mode 100644 index 00000000..a1bf3b56 --- /dev/null +++ b/libCacheSim-node/test.js @@ -0,0 +1,192 @@ +#!/usr/bin/env node + +/** + * Test suite for libCacheSim Node.js bindings + */ + +const libCacheSim = require('./index'); + +// ANSI color codes for better output +const colors = { + green: '\x1b[32m', + red: '\x1b[31m', + yellow: '\x1b[33m', + blue: '\x1b[34m', + reset: '\x1b[0m' +}; + +function log(color, message) { + console.log(`${colors[color]}${message}${colors.reset}`); +} + +function assert(condition, message) { + if (condition) { + log('green', `✓ ${message}`); + return true; + } else { + log('red', `✗ ${message}`); + return false; + } +} + +function runTests() { + let passed = 0; + let total = 0; + + function test(description, testFn) { + total++; + log('blue', `\nTest: ${description}`); + try { + if (testFn()) { + passed++; + } + } catch (error) { + log('red', `✗ ${description} - Error: ${error.message}`); + } + } + + log('yellow', '=== libCacheSim Node.js Bindings Test Suite ===\n'); + + // Test 1: Check if module loads correctly + test('Module loads correctly', () => { + return assert(typeof libCacheSim === 'object', 'libCacheSim module is an object') && + assert(typeof libCacheSim.runSim === 'function', 'runSim function exists') && + assert(typeof libCacheSim.runSimulation === 'function', 'runSimulation function exists') && + assert(typeof libCacheSim.getSupportedAlgorithms === 'function', 'getSupportedAlgorithms function exists') && + assert(typeof libCacheSim.getSupportedTraceTypes === 'function', 'getSupportedTraceTypes function exists'); + }); + + // Test 2: Check supported algorithms + test('Get supported algorithms', () => { + const algorithms = libCacheSim.getSupportedAlgorithms(); + return assert(Array.isArray(algorithms), 'Returns an array') && + assert(algorithms.length > 0, 'Array is not empty') && + assert(algorithms.includes('lru'), 'Includes LRU') && + assert(algorithms.includes('s3fifo'), 'Includes S3-FIFO') && + assert(algorithms.includes('sieve'), 'Includes Sieve'); + }); + + // Test 3: Check supported trace types + test('Get supported trace types', () => { + const traceTypes = libCacheSim.getSupportedTraceTypes(); + return assert(Array.isArray(traceTypes), 'Returns an array') && + assert(traceTypes.length > 0, 'Array is not empty') && + assert(traceTypes.includes('vscsi'), 'Includes VSCSI') && + assert(traceTypes.includes('csv'), 'Includes CSV'); + }); + + // Test 4: Run default simulation + test('Run default simulation', () => { + const result = libCacheSim.runSim(); + return assert(typeof result === 'object', 'Returns an object') && + assert(typeof result.totalRequests === 'number', 'Has totalRequests as number') && + assert(typeof result.hits === 'number', 'Has hits as number') && + assert(typeof result.misses === 'number', 'Has misses as number') && + assert(typeof result.hitRatio === 'number', 'Has hitRatio as number') && + assert(typeof result.missRatio === 'number', 'Has missRatio as number') && + assert(result.totalRequests === result.hits + result.misses, 'Total requests equals hits + misses') && + assert(Math.abs(result.hitRatio + result.missRatio - 1.0) < 0.0001, 'Hit ratio + miss ratio ≈ 1.0'); + }); + + // Test 5: Run custom simulation with different algorithms + test('Run custom simulations with different algorithms', () => { + const algorithms = ['lru', 'fifo', 's3fifo']; + let allPassed = true; + + for (const algo of algorithms) { + try { + const result = libCacheSim.runSimulation('../data/cloudPhysicsIO.vscsi', 'vscsi', algo, '1mb'); + if (!assert(typeof result === 'object', `${algo} returns object`) || + !assert(result.algorithm === algo, `${algo} has correct algorithm name`) || + !assert(result.totalRequests > 0, `${algo} has positive total requests`)) { + allPassed = false; + } + } catch (error) { + log('red', `✗ ${algo} simulation failed: ${error.message}`); + allPassed = false; + } + } + + return allPassed; + }); + + // Test 6: Test different cache sizes + test('Test different cache sizes', () => { + const sizes = ['512kb', '1mb', '2mb']; + let allPassed = true; + + for (const size of sizes) { + try { + const result = libCacheSim.runSimulation('../data/cloudPhysicsIO.vscsi', 'vscsi', 'lru', size); + if (!assert(typeof result.cacheSize === 'number', `${size} has numeric cache size`) || + !assert(result.cacheSize > 0, `${size} has positive cache size`)) { + allPassed = false; + } + } catch (error) { + log('red', `✗ ${size} simulation failed: ${error.message}`); + allPassed = false; + } + } + + return allPassed; + }); + + // Test 7: Error handling - invalid trace file + test('Error handling for invalid trace file', () => { + try { + libCacheSim.runSimulation('/nonexistent/file.vscsi', 'vscsi', 'lru', '1mb'); + return assert(false, 'Should throw error for nonexistent file'); + } catch (error) { + return assert(error.message.includes('Trace file does not exist'), 'Throws appropriate error for missing file'); + } + }); + + // Test 8: Error handling - invalid algorithm + test('Error handling for invalid algorithm', () => { + try { + libCacheSim.runSimulation('../data/cloudPhysicsIO.vscsi', 'vscsi', 'invalid_algo', '1mb'); + return assert(false, 'Should throw error for invalid algorithm'); + } catch (error) { + return assert(error.message.includes('Unsupported algorithm'), 'Throws appropriate error for invalid algorithm'); + } + }); + + // Test 9: Error handling - invalid trace type + test('Error handling for invalid trace type', () => { + try { + libCacheSim.runSimulation('../data/cloudPhysicsIO.vscsi', 'invalid_type', 'lru', '1mb'); + return assert(false, 'Should throw error for invalid trace type'); + } catch (error) { + return assert(error.message.includes('Unsupported trace type'), 'Throws appropriate error for invalid trace type'); + } + }); + + // Test 10: Performance test - measure execution time + test('Performance measurement', () => { + const startTime = process.hrtime.bigint(); + const result = libCacheSim.runSim(); + const endTime = process.hrtime.bigint(); + const durationMs = Number(endTime - startTime) / 1000000; + + log('blue', ` Processed ${result.totalRequests} requests in ${durationMs.toFixed(2)}ms`); + log('blue', ` Performance: ${(result.totalRequests / durationMs * 1000).toFixed(0)} requests/second`); + + return assert(durationMs < 5000, 'Simulation completes in reasonable time (< 5 seconds)'); + }); + + // Summary + log('yellow', '\n=== Test Summary ==='); + log(passed === total ? 'green' : 'red', + `Passed: ${passed}/${total} tests`); + + if (passed === total) { + log('green', 'All tests passed! 🎉'); + process.exit(0); + } else { + log('red', 'Some tests failed! ❌'); + process.exit(1); + } +} + +// Run the tests +runTests(); \ No newline at end of file From fcbddccb50c1277bdf0dd684478ff46981709590 Mon Sep 17 00:00:00 2001 From: Murphy Tian Date: Sun, 15 Jun 2025 16:38:24 +0800 Subject: [PATCH 8/8] [Style] change js cli tool name, from "libcachesim-cli" to "cachesim-js" --- libCacheSim-node/cli.js | 6 +++--- libCacheSim-node/libCacheSim-node.md | 14 +++++++------- libCacheSim-node/package.json | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/libCacheSim-node/cli.js b/libCacheSim-node/cli.js index 67106f17..938b9d72 100755 --- a/libCacheSim-node/cli.js +++ b/libCacheSim-node/cli.js @@ -49,7 +49,7 @@ function showHelp() { libcachesim-node CLI Usage: - libcachesim-cli --trace --type --algorithm --size + cachesim-js --trace --type --algorithm --size Options: --trace, -t Path to trace file (required) @@ -62,8 +62,8 @@ Options: --help, -h Show this help message Examples: - libcachesim-cli -t trace.vscsi --type vscsi -a lru -s 10mb - libcachesim-cli --trace data.csv --type csv --algorithm s3fifo --size 50mb + cachesim-js -t trace.vscsi --type vscsi -a lru -s 10mb + cachesim-js --trace data.csv --type csv --algorithm s3fifo --size 50mb `); } diff --git a/libCacheSim-node/libCacheSim-node.md b/libCacheSim-node/libCacheSim-node.md index 91de5f3e..27a33fc1 100644 --- a/libCacheSim-node/libCacheSim-node.md +++ b/libCacheSim-node/libCacheSim-node.md @@ -26,8 +26,8 @@ npm install -g . After global installation, you can use the CLI from any directory: ```bash -libcachesim-cli --help -libcachesim-cli --trace /path/to/trace.vscsi --type vscsi --algorithm lru --size 10mb +cachesim-js --help +cachesim-js --trace /path/to/trace.vscsi --type vscsi --algorithm lru --size 10mb ``` **Note:** Global installation requires the libCacheSim C++ library to be built first. Make sure you have: @@ -149,12 +149,12 @@ try { ## Command Line Interface -After global installation, you can use the `libcachesim-cli` command: +After global installation, you can use the `cachesim-js` command: ### CLI Usage ```bash -libcachesim-cli --trace --type --algorithm --size +cachesim-js --trace --type --algorithm --size ``` ### CLI Options @@ -169,13 +169,13 @@ libcachesim-cli --trace --type --algorithm --size ```bash # Basic simulation -libcachesim-cli -t trace.vscsi --type vscsi -a lru -s 10mb +cachesim-js -t trace.vscsi --type vscsi -a lru -s 10mb # Compare S3-FIFO with larger cache -libcachesim-cli --trace data.csv --type csv --algorithm s3fifo --size 50mb +cachesim-js --trace data.csv --type csv --algorithm s3fifo --size 50mb # Show help -libcachesim-cli --help +cachesim-js --help ``` ## Development diff --git a/libCacheSim-node/package.json b/libCacheSim-node/package.json index 906ed037..b0c52727 100644 --- a/libCacheSim-node/package.json +++ b/libCacheSim-node/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "main": "index.js", "bin": { - "libcachesim-cli": "./cli.js" + "cachesim-js": "./cli.js" }, "scripts": { "prebuild": "npm run ensure-libcachesim",