diff --git a/.github/workflows/npm-release.yml b/.github/workflows/npm-release.yml new file mode 100644 index 00000000..06de9b28 --- /dev/null +++ b/.github/workflows/npm-release.yml @@ -0,0 +1,168 @@ +name: NPM Release + +on: + release: + types: [published] + push: + branches: + - develop + paths: + - 'libCacheSim-node/**' + +env: + BUILD_TYPE: Release + +jobs: + create-release: + runs-on: ubuntu-latest + outputs: + release_created: ${{ steps.release.outputs.release_created }} + version: ${{ steps.package.outputs.version }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Get package version + id: package + working-directory: libCacheSim-node + run: | + VERSION=$(node -p "require('./package.json').version") + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "Version: $VERSION" + + - name: Check if release exists + id: check_release + run: | + VERSION="${{ steps.package.outputs.version }}" + if gh release view "v$VERSION" > /dev/null 2>&1; then + echo "Release v$VERSION already exists" + echo "exists=true" >> $GITHUB_OUTPUT + else + echo "Release v$VERSION does not exist" + echo "exists=false" >> $GITHUB_OUTPUT + fi + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Create GitHub Release + id: release + if: steps.check_release.outputs.exists == 'false' + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: v${{ steps.package.outputs.version }} + release_name: Release v${{ steps.package.outputs.version }} + body: | + Release v${{ steps.package.outputs.version }} + + ## Installation + ```bash + npm install libcachesim-node + ``` + + ## Supported Platforms + - Linux x64 + + Pre-compiled binaries are automatically downloaded during installation. + draft: false + prerelease: false + + build-and-publish: + needs: create-release + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' + registry-url: 'https://registry.npmjs.org' + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y build-essential cmake libglib2.0-dev libzstd-dev + + - name: Build libCacheSim + run: | + echo "Building libCacheSim for Linux x64..." + mkdir -p _build + cd _build + cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} .. -DCMAKE_VERBOSE_MAKEFILE=ON + echo "Starting build..." + make -j$(nproc) VERBOSE=1 + + - name: Prepare vendored library + run: | + mkdir -p libCacheSim-node/vendor/include + cp _build/liblibCacheSim.a libCacheSim-node/vendor/ + cp -r libCacheSim/include/* libCacheSim-node/vendor/include/ + + - name: Install Node.js dependencies + working-directory: libCacheSim-node + run: npm install + + - name: Build and upload prebuilt binary + working-directory: libCacheSim-node + run: | + echo "Building Node.js addon for Linux x64..." + echo "Node.js version: $(node --version)" + echo "NPM version: $(npm --version)" + ls -la ../ + ls -la ../_build/ + CFLAGS=-fPIC CXXFLAGS=-fPIC npx prebuild --upload-all --verbose + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Test binary + working-directory: libCacheSim-node + run: | + echo "Testing binary load for Linux x64..." + ls -la + ls -la prebuilds/ || echo "No prebuilds directory found" + node -e "console.log('Testing binary load...'); try { require('./index.js'); console.log('Binary loaded successfully!'); } catch(e) { console.error('Failed to load binary:', e); process.exit(1); }" + + publish-npm: + needs: build-and-publish + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' + registry-url: 'https://registry.npmjs.org' + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y build-essential cmake libglib2.0-dev libzstd-dev + + - name: Build libCacheSim + run: | + mkdir -p _build + cd _build + cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} .. + make -j$(nproc) + + - name: Prepare vendored library + run: | + mkdir -p libCacheSim-node/vendor/include + cp _build/liblibCacheSim.a libCacheSim-node/vendor/ + cp -r libCacheSim/include/* libCacheSim-node/vendor/include/ + + - name: Publish to NPM + working-directory: libCacheSim-node + run: npm publish --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} \ No newline at end of file diff --git a/libCacheSim-node/README.md b/libCacheSim-node/README.md new file mode 100644 index 00000000..14d30704 --- /dev/null +++ b/libCacheSim-node/README.md @@ -0,0 +1,201 @@ +# libCacheSim Node.js Bindings + +Node.js bindings for libCacheSim - A high-performance cache simulator and analysis library supporting LRU, FIFO, S3-FIFO, Sieve and other caching algorithms. + +## Features + +- **High Performance**: Built on the optimized libCacheSim C library +- **Multiple Algorithms**: Support for LRU, FIFO, LFU, ARC, Clock, S3-FIFO, Sieve, and more +- **Various Trace Types**: Support for vscsi, csv, txt, binary, and oracle trace formats +- **Pre-compiled Binaries**: Fast installation with no build tools required +- **Cross-platform**: Support for Linux (x64) and macOS (x64, ARM64) + +## Installation + +```bash +npm install libcachesim-node +``` + +The package includes pre-compiled binaries for supported platforms. No additional build tools or dependencies are required for end users. + +### Supported Platforms + +- **Linux**: x64 (Ubuntu 18.04+, other distributions with compatible glibc) +- **macOS**: x64 (Intel) and ARM64 (Apple Silicon) + +If pre-compiled binaries are not available for your platform, please check the releases page for updates or submit an issue. + +## Quick Start + +```javascript +const { runSimulation, getSupportedAlgorithms } = require('libcachesim-node'); + +// Get supported algorithms +console.log('Supported algorithms:', getSupportedAlgorithms()); + +// Run a cache simulation +const result = runSimulation( + '/path/to/trace.vscsi', // Path to trace file + 'vscsi', // Trace type + 's3fifo', // Cache algorithm + '1mb' // Cache size +); + +console.log('Simulation results:', result); +``` + +## API Reference + +### `runSimulation(tracePath, traceType, algorithm, cacheSize)` + +Run a cache simulation with specified parameters. + +**Parameters:** +- `tracePath` (string): Path to the trace file +- `traceType` (string): Type of trace file ('vscsi', 'csv', 'txt', 'binary', 'oracle') +- `algorithm` (string): Cache replacement algorithm +- `cacheSize` (string): Cache size (e.g., '1mb', '512kb', '2gb') + +**Returns:** Object containing simulation results including hit rate, miss count, etc. + +### `getSupportedAlgorithms()` + +Get a list of supported cache algorithms. + +**Returns:** Array of algorithm names + +### `getSupportedTraceTypes()` + +Get a list of supported trace file types. + +**Returns:** Array of trace type names + +## Cache Algorithms + +The following cache replacement algorithms are supported: + +- **LRU** (Least Recently Used) +- **FIFO** (First In, First Out) +- **LFU** (Least Frequently Used) +- **ARC** (Adaptive Replacement Cache) +- **Clock** (Clock/Second Chance) +- **S3-FIFO** (Simple, Scalable, Scan-resistant FIFO) +- **Sieve** (Eviction algorithm with lazy promotion) + +## Trace File Formats + +- **vscsi**: VMware vSCSI trace format +- **csv**: Comma-separated values format +- **txt**: Plain text format +- **binary**: Binary trace format +- **oracle**: Oracle optimal algorithm simulation + +## Command Line Interface + +The package includes a command-line interface: + +```bash +# Install globally for CLI access +npm install -g libcachesim-node + +# Run simulation from command line +cachesim-js --trace /path/to/trace.vscsi --algorithm s3fifo --size 1mb +``` + +## Development + +### Building from Source + +If you need to build from source or contribute to development: + +```bash +# Clone the repository +git clone https://github.com/1a1a11a/libCacheSim.git +cd libCacheSim/libCacheSim-node + +# Install dependencies +npm install + +# Build from source (requires cmake, build tools) +npm run build-from-source + +# Run tests +npm test +``` + +### Requirements for Building from Source + +- Node.js 14+ +- CMake 3.10+ +- C/C++ compiler (GCC, Clang, or MSVC) +- System dependencies: + - Linux: `build-essential cmake libglib2.0-dev libzstd-dev` + - macOS: `cmake glib zstd` (via Homebrew) + +## Architecture + +This package uses `prebuild-install` for binary distribution: + +1. **Pre-compiled Binaries**: Automatically downloaded from GitHub releases during installation +2. **Automated Building**: GitHub Actions automatically builds binaries for all supported platforms +3. **Standard Tooling**: Uses industry-standard `prebuild` and `prebuild-install` packages + +## Troubleshooting + +### Installation Issues + +If installation fails, try the following: + +```bash +# Clear npm cache +npm cache clean --force + +# Reinstall with verbose logging +npm install libcachesim-node --verbose + +# Force source compilation +npm install libcachesim-node --build-from-source +``` + +### Binary Loading Issues + +If you see binary loading errors: + +1. Ensure your platform is supported +2. Check that the `prebuilds` directory exists and contains your platform's binary +3. Try reinstalling the package +4. Check Node.js version compatibility (requires Node.js 14+) + +### Build from Source Issues + +If source compilation fails: + +1. Install required system dependencies +2. Ensure CMake 3.10+ is available +3. Check that libCacheSim builds successfully: `cd .. && mkdir _build && cd _build && cmake .. && make` + +## Contributing + +Contributions are welcome! Please see the main [libCacheSim repository](https://github.com/1a1a11a/libCacheSim) for contribution guidelines. + +## License + +MIT License - see the LICENSE file for details. + +## Related Projects + +- [libCacheSim](https://github.com/1a1a11a/libCacheSim) - The core C library +- [libCacheSim Python bindings](https://github.com/1a1a11a/libCacheSim/tree/develop/libCacheSim/pyBindings) - Python interface + +## Citation + +If you use libCacheSim in your research, please cite: + +```bibtex +@misc{libcachesim, + title={libCacheSim: A High-Performance Cache Simulator}, + author={Tian, Murphy and others}, + year={2023}, + url={https://github.com/1a1a11a/libCacheSim} +} +``` \ No newline at end of file diff --git a/libCacheSim-node/binding.gyp b/libCacheSim-node/binding.gyp index c89f1dd7..a1bf61e7 100644 --- a/libCacheSim-node/binding.gyp +++ b/libCacheSim-node/binding.gyp @@ -5,15 +5,11 @@ "sources": [ "binding.cc" ], "include_dirs": [ " { - 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); -} -``` - -## Command Line Interface - -After global installation, you can use the `cachesim-js` command: - -### CLI Usage - -```bash -cachesim-js --trace --type --algorithm --size -``` - -### 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 -cachesim-js -t trace.vscsi --type vscsi -a lru -s 10mb - -# Compare S3-FIFO with larger cache -cachesim-js --trace data.csv --type csv --algorithm s3fifo --size 50mb - -# Show help -cachesim-js --help -``` -## Development - -### Building from Source - -```bash -# Clean build -npm run clean -npm run build - -# Debug build with debugging symbols -DEBUG=1 npm run build -``` - -### Running Tests - -```bash -# Run test suite -npm test -``` \ No newline at end of file diff --git a/libCacheSim-node/package.json b/libCacheSim-node/package.json index b0c52727..80e60e08 100644 --- a/libCacheSim-node/package.json +++ b/libCacheSim-node/package.json @@ -6,13 +6,9 @@ "cachesim-js": "./cli.js" }, "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:+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", - "prepack": "npm run build" + "install": "prebuild-install || node-gyp rebuild", + "prebuild": "prebuild --all --strip --verbose" }, "keywords": [ "cache", @@ -31,7 +27,7 @@ "type": "git", "url": "https://github.com/1a1a11a/libCacheSim" }, - "homepage": "https://github.com/1a1a11a/libCacheSim/tree/develop/libCacheSim-node", + "homepage": "https://github.com/1a1a11a/libCacheSim/tree/main/libCacheSim-node", "bugs": { "url": "https://github.com/1a1a11a/libCacheSim/issues" }, @@ -39,16 +35,27 @@ "node": ">=14.0.0" }, "dependencies": { - "node-addon-api": "^8.3.1" + "node-addon-api": "^8.3.1", + "prebuild-install": "^7.1.2" + }, + "devDependencies": { + "node-gyp": "^10.0.0", + "prebuild": "^13.0.1" }, - "devDependencies": {}, "files": [ "index.js", "cli.js", "binding.cc", "binding.gyp", - "README.md" + "README.md", + "vendor" ], + "binary": { + "module_name": "cachesim-addon", + "module_path": "./build/Release/", + "remote_path": "https://github.com/1a1a11a/libCacheSim/releases/download/", + "package_name": "{module_name}-v{version}-{node_abi}-{platform}-{arch}.tar.gz" + }, "publishConfig": { "registry": "https://registry.npmjs.org/" } diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..9aa73453 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "libCacheSim", + "lockfileVersion": 3, + "requires": true, + "packages": {} +}