Skip to content

Commit 3540724

Browse files
authored
Adding benchmarks (#189)
* Updating README.md * Updating README.md, adding benchmarks
1 parent 9f85e3d commit 3540724

File tree

8 files changed

+1347
-4
lines changed

8 files changed

+1347
-4
lines changed

README.md

Lines changed: 89 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# filesize.js
22

3-
[![downloads](https://img.shields.io/npm/dt/filesize.svg)](https://www.npmjs.com/package/filesize)
4-
[![npm version](https://badge.fury.io/js/filesize.svg)](https://badge.fury.io/js/filesize)
3+
[![downloads](https://img.shields.io/npm/dt/filesize.svg)](https://www.npmjs.com/package/filesize.js)
4+
[![npm version](https://badge.fury.io/js/filesize.svg)](https://badge.fury.io/js/filesize.js)
55
[![Node.js Version](https://img.shields.io/node/v/filesize.svg)](https://nodejs.org/)
66
[![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
7-
[![Build Status](https://github.com/avoidwork/woodland/actions/workflows/ci.yml/badge.svg)](https://github.com/avoidwork/filesize/actions)
7+
[![Build Status](https://github.com/avoidwork/woodland/actions/workflows/ci.yml/badge.svg)](https://github.com/avoidwork/filesize.js/actions)
88

99
A lightweight, high-performance file size utility for JavaScript that converts bytes to human-readable strings. Works in both Node.js and browser environments with comprehensive format support.
1010

@@ -117,6 +117,92 @@ The test suite comprehensively covers:
117117
* **Error handling**: Invalid inputs and boundary conditions
118118
* **Partial functions**: All option combinations with curried functions
119119

120+
## Performance Benchmarks
121+
122+
filesize.js is optimized for high performance with comprehensive benchmarks covering various usage patterns:
123+
124+
### 🚀 Performance Overview
125+
126+
| Scenario | Operations/sec | Notes |
127+
|----------|----------------|-------|
128+
| **Basic conversion** | ~8-19M ops/sec | Fastest operations (small numbers) |
129+
| **Large numbers** | ~8-15M ops/sec | Consistent performance |
130+
| **With options** | ~2-8M ops/sec | Depends on option complexity |
131+
| **Locale formatting** | ~85K ops/sec | Most expensive operation |
132+
| **Partial functions** | ~6-8M ops/sec | ~10-20% overhead, amortized |
133+
134+
### 📊 Detailed Benchmark Results
135+
136+
#### Basic Performance
137+
- **filesize(0)**: 18.8M ops/sec
138+
- **filesize(1024)**: 14.5M ops/sec
139+
- **filesize(1GB)**: 8.5M ops/sec
140+
- **With bits=true**: 13.1M ops/sec
141+
- **With standard="iec"**: 7.9M ops/sec
142+
- **With fullform=true**: 6.6M ops/sec
143+
- **Object output**: 9.0M ops/sec
144+
145+
#### Options Performance Impact
146+
- **Default options**: 6.4M ops/sec (baseline)
147+
- **bits=true**: 1.66x slower
148+
- **pad=true**: 2.74x slower
149+
- **locale="en-US"**: 75x slower (significant overhead)
150+
- **standard="iec"**: 1.12x slower
151+
- **output="object"**: 0.96x faster
152+
- **Complex combinations**: 1.6-2.1x slower
153+
154+
#### Stress Test Results
155+
- **Edge cases**: 2.0M ops/sec (90% success rate)
156+
- **Very large numbers**: 3.7M ops/sec (100% success)
157+
- **BigInt values**: 2.8M ops/sec (100% success)
158+
- **Memory pressure**: 48K ops/sec (100% success)
159+
- **Performance consistency**: 84.7% (10 runs average)
160+
161+
#### Partial Function Performance
162+
- **Direct calls**: 8.0M ops/sec (baseline)
163+
- **Simple partial**: 6.7M ops/sec (1.20x slower)
164+
- **Complex partial**: 5.6M ops/sec (1.42x slower)
165+
- **Partial with locale**: 84K ops/sec (95x slower)
166+
167+
### 💡 Performance Insights
168+
169+
**Excellent Performance (>1M ops/sec)**
170+
- Basic conversions with minimal options
171+
- Standard output formats (string, array, object)
172+
- IEC and JEDEC standards
173+
174+
**Good Performance (100K-1M ops/sec)**
175+
- Complex option combinations
176+
- Precision and rounding operations
177+
- Fullform output
178+
179+
**Use Sparingly (<100K ops/sec)**
180+
- Locale formatting (significant overhead)
181+
- Complex locale configurations
182+
183+
### 🎯 Optimization Tips
184+
185+
1. **Cache partial functions** for repeated operations with same options
186+
2. **Avoid locale formatting** in performance-critical code
187+
3. **Use object output** for fastest structured data
188+
4. **Batch similar operations** together
189+
5. **Profile your specific usage patterns**
190+
191+
### Running Benchmarks
192+
193+
```bash
194+
# Run all benchmarks
195+
cd benchmarks && node index.js
196+
197+
# Run specific benchmark
198+
node benchmarks/basic-performance.js
199+
200+
# With garbage collection (more accurate)
201+
node --expose-gc benchmarks/index.js
202+
```
203+
204+
*Benchmarks run on macOS ARM64, Node.js v23.10.0, 12 CPU cores, 24GB RAM*
205+
120206
## API Reference
121207

122208
### Functions

benchmarks/README.md

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
# Filesize.js Benchmarks
2+
3+
This directory contains comprehensive performance benchmarks for the filesize.js library. The benchmarks are designed to measure performance across different usage patterns, option combinations, and edge cases.
4+
5+
## 📁 Benchmark Files
6+
7+
### 🏃 `basic-performance.js`
8+
Tests fundamental performance characteristics of the filesize function:
9+
- Basic conversion performance with various input sizes
10+
- Different option combinations
11+
- Memory usage analysis
12+
- Baseline performance metrics
13+
14+
### ⚙️ `options-benchmark.js`
15+
Analyzes the performance impact of different configuration options:
16+
- Individual option performance costs
17+
- Complex option combinations
18+
- Relative performance comparisons
19+
- Optimization insights
20+
21+
### 🔥 `stress-test.js`
22+
Evaluates performance under challenging conditions:
23+
- Edge cases and extreme values
24+
- Error handling performance
25+
- Memory pressure scenarios
26+
- Performance consistency analysis
27+
- BigInt support testing
28+
29+
### 🔧 `partial-benchmark.js`
30+
Focuses on the partial function and functional programming patterns:
31+
- Partial function vs direct calls
32+
- Function creation overhead
33+
- Functional programming patterns
34+
- Currying performance analysis
35+
36+
### 🎯 `index.js`
37+
Main benchmark runner that executes all test suites:
38+
- Orchestrates all benchmark execution
39+
- Provides comprehensive summary
40+
- System information reporting
41+
- Error handling and reporting
42+
43+
## 🚀 Running Benchmarks
44+
45+
### Run All Benchmarks
46+
```bash
47+
cd benchmarks
48+
node index.js
49+
```
50+
51+
### Run Individual Benchmarks
52+
```bash
53+
# Basic performance tests
54+
node basic-performance.js
55+
56+
# Options impact analysis
57+
node options-benchmark.js
58+
59+
# Stress testing
60+
node stress-test.js
61+
62+
# Partial function analysis
63+
node partial-benchmark.js
64+
```
65+
66+
### Enhanced Performance Mode
67+
For more accurate memory-related benchmarks, run with garbage collection exposed:
68+
```bash
69+
node --expose-gc index.js
70+
```
71+
72+
## 📊 Understanding Results
73+
74+
### Performance Metrics
75+
- **Ops/sec**: Operations per second (higher is better)
76+
- **Avg (ms)**: Average execution time per operation (lower is better)
77+
- **Total (ms)**: Total execution time for all iterations
78+
- **Relative**: Performance relative to baseline (lower multiplier is better)
79+
80+
### Benchmark Categories
81+
82+
#### 🎯 **Basic Performance**
83+
- Measures core function performance
84+
- Tests with various input sizes (0 bytes to MAX_SAFE_INTEGER)
85+
- Establishes baseline performance characteristics
86+
87+
#### ⚙️ **Options Impact**
88+
- Quantifies performance cost of each option
89+
- Identifies expensive operations (locale formatting, complex outputs)
90+
- Helps optimize option usage
91+
92+
#### 🔥 **Stress Testing**
93+
- Validates performance under extreme conditions
94+
- Tests error handling efficiency
95+
- Measures performance consistency
96+
- Evaluates memory usage patterns
97+
98+
#### 🔧 **Functional Programming**
99+
- Compares partial functions vs direct calls
100+
- Analyzes currying overhead
101+
- Tests functional composition patterns
102+
103+
## 📈 Performance Insights
104+
105+
### General Findings
106+
- **Baseline Performance**: ~500K-1M+ ops/sec for basic conversions
107+
- **Locale Formatting**: Significant overhead (~2-5x slower)
108+
- **Object Output**: Minimal overhead (~10-20% slower)
109+
- **Complex Options**: Compound performance impact
110+
- **Partial Functions**: ~10-30% overhead, amortized over multiple uses
111+
112+
### Optimization Tips
113+
1. **Cache Partial Functions**: Reuse partial functions for repeated operations
114+
2. **Avoid Locale When Possible**: Use locale formatting sparingly
115+
3. **Prefer String Output**: Fastest output format for most use cases
116+
4. **Batch Operations**: Group similar operations together
117+
5. **Profile Your Usage**: Run benchmarks with your specific patterns
118+
119+
## 🔧 Benchmark Configuration
120+
121+
### Iteration Counts
122+
- **Basic Performance**: 100,000 iterations
123+
- **Options Testing**: 50,000 iterations
124+
- **Stress Testing**: 10,000 iterations
125+
- **Partial Functions**: 100,000 iterations
126+
127+
### Warmup Periods
128+
All benchmarks include warmup periods to ensure JIT optimization and stable measurements.
129+
130+
### Memory Management
131+
- Garbage collection calls between tests (when available)
132+
- Memory pressure testing
133+
- Memory usage monitoring
134+
135+
## 🛠️ Customizing Benchmarks
136+
137+
### Adding New Tests
138+
1. Create a new benchmark file in the `benchmarks` directory
139+
2. Follow the existing pattern for benchmark functions
140+
3. Add the file to `BENCHMARK_FILES` in `index.js`
141+
142+
### Modifying Parameters
143+
- Adjust `ITERATIONS` constants for different test durations
144+
- Modify test data sets for specific scenarios
145+
- Add new option combinations for testing
146+
147+
### Example Custom Benchmark
148+
```javascript
149+
import { filesize } from '../dist/filesize.js';
150+
151+
const ITERATIONS = 10000;
152+
153+
function benchmark(testName, testFunction, iterations = ITERATIONS) {
154+
// Warmup
155+
for (let i = 0; i < 1000; i++) {
156+
testFunction();
157+
}
158+
159+
const startTime = process.hrtime.bigint();
160+
for (let i = 0; i < iterations; i++) {
161+
testFunction();
162+
}
163+
const endTime = process.hrtime.bigint();
164+
165+
const totalTime = Number(endTime - startTime) / 1000000;
166+
const avgTime = totalTime / iterations;
167+
const opsPerSecond = Math.round(1000 / avgTime);
168+
169+
return { testName, opsPerSecond, avgTime };
170+
}
171+
172+
// Your custom test
173+
const result = benchmark('Custom test', () => {
174+
return filesize(1024 * 1024, { /* your options */ });
175+
});
176+
177+
console.log(result);
178+
```
179+
180+
## 🔍 Interpreting Results
181+
182+
### Performance Baselines
183+
- **Excellent**: >1M ops/sec
184+
- **Good**: 500K-1M ops/sec
185+
- **Acceptable**: 100K-500K ops/sec
186+
- **Slow**: <100K ops/sec
187+
188+
### When to Optimize
189+
- If your use case requires >100K operations/sec
190+
- When performance regression is detected
191+
- Before production deployment with high load
192+
- When adding new features or options
193+
194+
### Profiling Your Application
195+
1. Run benchmarks with your specific usage patterns
196+
2. Identify bottlenecks in your option combinations
197+
3. Test with your actual data sizes
198+
4. Measure end-to-end performance in your application
199+
200+
## 🤝 Contributing
201+
202+
When contributing performance improvements:
203+
1. Run all benchmarks before and after changes
204+
2. Document performance impacts in commit messages
205+
3. Add new benchmarks for new features
206+
4. Ensure no significant regressions in existing tests
207+
208+
## 📚 Additional Resources
209+
210+
- [MDN Performance Best Practices](https://developer.mozilla.org/en-US/docs/Web/Performance)
211+
- [Node.js Performance Hooks](https://nodejs.org/api/perf_hooks.html)
212+
- [V8 Performance Tips](https://v8.dev/blog/optimizing-cpp-and-js)

0 commit comments

Comments
 (0)