Skip to content

Commit b64ac5d

Browse files
committed
chore: wip
1 parent 47f6873 commit b64ac5d

File tree

21 files changed

+1448
-104
lines changed

21 files changed

+1448
-104
lines changed

.performance-summary.md

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# ⚡ Performance Optimization Summary
2+
3+
## 🏆 Achievement: 100% Win Rate!
4+
5+
nanofaker now **wins ALL 9 benchmarks** against major JavaScript/TypeScript faker libraries!
6+
7+
## 📊 Results Summary
8+
9+
### Before Optimizations
10+
- ✅ 7 out of 9 benchmarks won
11+
- ⚡ 3.61x faster than @faker-js/faker
12+
- 📛 Full Name: 2.76M ops/s (lost to @ngneat/falso)
13+
- 📞 Phone Number: 2.88M ops/s (lost to chance)
14+
15+
### After Optimizations
16+
-**9 out of 9 benchmarks won** (100% win rate!)
17+
-**6.57x faster than @faker-js/faker**
18+
- 📛 Full Name: **31.35M ops/s** (11.4x improvement!)
19+
- 📞 Phone Number: **9.77M ops/s** (3.4x improvement!)
20+
- 📊 Complex Objects: **7.97ms** for 10k (1.9x improvement!)
21+
22+
## 🚀 Key Optimizations
23+
24+
### 1. Direct Array Access
25+
Eliminated function call overhead for unseeded random by using direct `Math.random()` instead of `this.int()`.
26+
27+
**Impact**: 30-40% faster array element selection
28+
29+
### 2. Optimized String Replacement
30+
Replaced regex-based `replaceSymbols()` with character-by-character iteration and pre-computed alphabet arrays.
31+
32+
**Impact**: Phone number generation **3.4x faster**
33+
34+
### 3. Template Literals for Full Names
35+
Replaced array creation + join with direct template literals.
36+
37+
**Impact**: Full name generation **11.4x faster**
38+
39+
### 4. Eliminated Array Spreading
40+
Avoided creating combined arrays by calculating indices across multiple arrays.
41+
42+
**Impact**: Contributed to overall name generation speedup
43+
44+
### 5. Static Pre-computed Arrays
45+
Moved alphabet and digit arrays to static readonly properties.
46+
47+
**Impact**: Eliminated repeated string splits
48+
49+
## 📈 Performance Comparison vs @faker-js/faker
50+
51+
| Operation | nanofaker | @faker-js/faker | Speedup |
52+
|-----------|-----------|-----------------|---------|
53+
| Full Name Generation | 31.35M ops/s | 537.95K ops/s | **58x faster** |
54+
| Phone Number Generation | 9.77M ops/s | 2.05M ops/s | **4.8x faster** |
55+
| City Generation | 39.63M ops/s | 779.69K ops/s | **51x faster** |
56+
| Country Generation | 38.55M ops/s | 15.83M ops/s | **2.4x faster** |
57+
| Company Name Generation | 37.64M ops/s | 557.33K ops/s | **68x faster** |
58+
| Product Generation | 30.65M ops/s | 17.78M ops/s | **1.7x faster** |
59+
| UUID Generation | 1.02M ops/s | 532.96K ops/s | **1.9x faster** |
60+
| Email Generation | 1.96M ops/s | 567.44K ops/s | **3.5x faster** |
61+
| Complex Objects (10k) | 7.97ms | 52.39ms | **6.6x faster** |
62+
63+
## 🎯 Trade-offs
64+
65+
### Benefits
66+
-**6.57x average speedup** vs @faker-js/faker
67+
-**100% win rate** against all competitors
68+
- ✅ Maintains API compatibility
69+
- ✅ Maintains seeded reproducibility
70+
- ✅ All tests pass
71+
72+
### Costs
73+
- ~5% larger code size (branching for seeded vs unseeded)
74+
- Slightly more complex internal logic
75+
76+
## 📦 Files Modified
77+
78+
### Core Optimizations
79+
- `packages/core/src/random.ts`
80+
- Added static ALPHABET and DIGITS arrays
81+
- Optimized `arrayElement()` for unseeded random
82+
- Completely rewrote `replaceSymbols()` with fast path
83+
84+
- `packages/core/src/modules/person.ts`
85+
- Optimized `fullName()` with template literals
86+
- Optimized `firstName()` to avoid array spreading
87+
88+
### Documentation Updates
89+
- `BENCHMARKS.md` - Updated with 100% win rate
90+
- `README.md` - Updated performance section
91+
- `docs/comparison.md` - Updated benchmark comparisons
92+
- `docs/index.md` - Updated hero performance claim
93+
- `docs/features/performance.md` - Updated performance table
94+
95+
### Benchmarks
96+
- `packages/benchmarks/` - New benchmarks package
97+
- Full comparison suite
98+
- Tests against 4 major libraries
99+
- Updated to @faker-js/faker v10.0.0
100+
- Detailed optimization documentation
101+
102+
## 🎉 Conclusion
103+
104+
nanofaker is now the **fastest faker library** in the JavaScript/TypeScript ecosystem, winning every single benchmark category while maintaining full API compatibility and feature parity.
105+
106+
**Run benchmarks:**
107+
```bash
108+
bun run bench
109+
```
110+
111+
**Verify tests:**
112+
```bash
113+
bun test
114+
```

BENCHMARKS.md

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
# Performance Benchmarks
2+
3+
Comprehensive benchmarks comparing nanofaker against other popular JavaScript/TypeScript faker libraries.
4+
5+
## Latest Results
6+
7+
**Environment:**
8+
9+
- Runtime: Bun v1.2.21
10+
- Platform: macOS ARM64 (Apple Silicon)
11+
- Date: 2025-10-04
12+
13+
## Summary
14+
15+
**nanofaker won 9 out of 9 benchmarks** (100% win rate!)
16+
**6.57x faster than @faker-js/faker on average**
17+
18+
## Detailed Results
19+
20+
### 📛 Full Name Generation
21+
22+
| Library | ops/s | avg time | margin | vs fastest |
23+
|---------|-------|----------|--------|------------|
24+
| **nanofaker** | 31.35M ops/s | 0.0319ms | ±0.47% | **(fastest)**|
25+
| @ngneat/falso | 3.76M ops/s | 0.2659ms | ±0.95% | 0.12x |
26+
| casual | 2.61M ops/s | 0.3833ms | ±0.96% | 0.08x |
27+
| chance | 2.56M ops/s | 0.3900ms | ±1.01% | 0.08x |
28+
| @faker-js/faker | 537.95K ops/s | 1.8589ms | ±1.40% | 0.02x |
29+
30+
### 📧 Email Generation
31+
32+
| Library | ops/s | avg time | margin | vs fastest |
33+
|---------|-------|----------|--------|------------|
34+
| **nanofaker** | 1.96M ops/s | 0.5098ms | ±1.43% | **(fastest)**|
35+
| @ngneat/falso | 1.81M ops/s | 0.5512ms | ±1.12% | 0.92x |
36+
| casual | 1.09M ops/s | 0.9172ms | ±0.79% | 0.56x |
37+
| chance | 849.49K ops/s | 1.1772ms | ±1.43% | 0.43x |
38+
| @faker-js/faker | 567.44K ops/s | 1.7623ms | ±1.16% | 0.29x |
39+
40+
### 📞 Phone Number Generation
41+
42+
| Library | ops/s | avg time | margin | vs fastest |
43+
|---------|-------|----------|--------|------------|
44+
| **nanofaker** | 9.77M ops/s | 0.1024ms | ±1.13% | **(fastest)**|
45+
| chance | 2.68M ops/s | 0.3735ms | ±1.21% | 0.27x |
46+
| @faker-js/faker | 2.05M ops/s | 0.4869ms | ±0.99% | 0.21x |
47+
| casual | 1.23M ops/s | 0.8117ms | ±0.61% | 0.13x |
48+
| @ngneat/falso | 470.39K ops/s | 2.1259ms | ±0.87% | 0.05x |
49+
50+
### 🏙️ City Generation
51+
52+
| Library | ops/s | avg time | margin | vs fastest |
53+
|---------|-------|----------|--------|------------|
54+
| **nanofaker** | 39.63M ops/s | 0.0252ms | ±0.58% | **(fastest)**|
55+
| @ngneat/falso | 18.13M ops/s | 0.0552ms | ±1.20% | 0.46x |
56+
| casual | 1.99M ops/s | 0.5020ms | ±0.89% | 0.05x |
57+
| chance | 1.12M ops/s | 0.8969ms | ±1.19% | 0.03x |
58+
| @faker-js/faker | 779.69K ops/s | 1.2826ms | ±1.29% | 0.02x |
59+
60+
### 🌍 Country Generation
61+
62+
| Library | ops/s | avg time | margin | vs fastest |
63+
|---------|-------|----------|--------|------------|
64+
| **nanofaker** | 38.55M ops/s | 0.0259ms | ±0.71% | **(fastest)**|
65+
| casual | 18.98M ops/s | 0.0527ms | ±1.08% | 0.49x |
66+
| @ngneat/falso | 17.93M ops/s | 0.0558ms | ±1.14% | 0.46x |
67+
| @faker-js/faker | 15.83M ops/s | 0.0632ms | ±0.80% | 0.41x |
68+
| chance | 2.53M ops/s | 0.3946ms | ±1.47% | 0.07x |
69+
70+
### 🏢 Company Name Generation
71+
72+
| Library | ops/s | avg time | margin | vs fastest |
73+
|---------|-------|----------|--------|------------|
74+
| **nanofaker** | 37.64M ops/s | 0.0266ms | ±1.15% | **(fastest)**|
75+
| @ngneat/falso | 17.78M ops/s | 0.0562ms | ±1.09% | 0.47x |
76+
| casual | 2.32M ops/s | 0.4317ms | ±0.99% | 0.06x |
77+
| chance | 800.45K ops/s | 1.2493ms | ±1.61% | 0.02x |
78+
| @faker-js/faker | 557.33K ops/s | 1.7943ms | ±1.66% | 0.01x |
79+
80+
### 🛍️ Product Generation
81+
82+
| Library | ops/s | avg time | margin | vs fastest |
83+
|---------|-------|----------|--------|------------|
84+
| **nanofaker** | 30.65M ops/s | 0.0326ms | ±0.98% | **(fastest)**|
85+
| casual | 21.34M ops/s | 0.0469ms | ±0.65% | 0.70x |
86+
| @faker-js/faker | 17.78M ops/s | 0.0562ms | ±0.49% | 0.58x |
87+
| @ngneat/falso | 365.26K ops/s | 2.7378ms | ±0.83% | 0.01x |
88+
89+
### 🔑 UUID Generation
90+
91+
| Library | ops/s | avg time | margin | vs fastest |
92+
|---------|-------|----------|--------|------------|
93+
| **nanofaker** | 1.02M ops/s | 0.9849ms | ±0.26% | **(fastest)**|
94+
| @ngneat/falso | 555.23K ops/s | 1.8011ms | ±0.52% | 0.55x |
95+
| @faker-js/faker | 531.61K ops/s | 1.8811ms | ±0.55% | 0.52x |
96+
| casual | 464.73K ops/s | 2.1518ms | ±0.53% | 0.46x |
97+
| chance | 428.55K ops/s | 2.3335ms | ±0.78% | 0.42x |
98+
99+
### 📊 Complex User Object (10,000 records)
100+
101+
Generates 10,000 complete user objects with:
102+
103+
- Full Name
104+
- Email
105+
- Phone Number
106+
- City
107+
- Country
108+
109+
| Library | Total Time | μs/record | vs fastest |
110+
|---------|------------|-----------|------------|
111+
| **nanofaker** | 7.97ms | 0.7975μs | **(fastest)**|
112+
| casual | 25.44ms | 2.5442μs | 0.31x |
113+
| @ngneat/falso | 28.64ms | 2.8644μs | 0.28x |
114+
| chance | 33.12ms | 3.3117μs | 0.24x |
115+
| @faker-js/faker | 52.39ms | 5.2394μs | 0.15x |
116+
117+
## Libraries Tested
118+
119+
- **nanofaker** (this library) - Performance-focused faker with 26 locales
120+
- **@faker-js/faker** v10.0.0 - Most popular faker library
121+
- **chance** v1.1.13 - Popular random generator
122+
- **casual** v1.6.2 - Lightweight fake data generator
123+
- **@ngneat/falso** v7.4.0 - TypeScript-first random data generator
124+
125+
## Key Takeaways
126+
127+
### Where nanofaker Excels
128+
129+
1. **Full name generation** - 31.35M ops/s (8.3x faster than nearest competitor)
130+
2. **Phone number generation** - 9.77M ops/s (3.6x faster than nearest competitor)
131+
3. **Simple data types** (City, Country, Company, Product) - 30-40M ops/s
132+
4. **Email generation** - 1.96M ops/s (fastest)
133+
5. **Complex objects** - 6.57x faster than @faker-js/faker
134+
6. **Consistency** - Low margin of error (±0.47-1.43%)
135+
7. **100% win rate** - Fastest in ALL categories
136+
137+
### Performance vs @faker-js/faker
138+
139+
nanofaker is significantly faster across all categories:
140+
141+
- **Full Name**: 58.3x faster
142+
- **Phone Number**: 4.8x faster
143+
- **City**: 50.8x faster
144+
- **Country**: 2.4x faster
145+
- **Company**: 67.5x faster
146+
- **Product**: 1.7x faster
147+
- **UUID**: 1.9x faster
148+
- **Email**: 3.5x faster
149+
- **Complex Objects**: 6.6x faster
150+
151+
### Average improvement: 6.57x faster
152+
153+
## Running Benchmarks
154+
155+
```bash
156+
# From repository root
157+
bun run bench
158+
159+
# From benchmarks package
160+
cd packages/benchmarks
161+
bun run bench
162+
```
163+
164+
## Benchmark Configuration
165+
166+
- **Time per benchmark**: 500ms
167+
- **Warmup**: Yes (automatic)
168+
- **Iterations**: Automatic (based on time budget)
169+
- **Benchmarking library**: tinybench v2.9.0
170+
171+
## Why nanofaker is Fast
172+
173+
1. **Direct array access** - O(1) constant-time lookups
174+
2. **Minimal overhead** - Lightweight abstraction layer
175+
3. **No complex computations** - Simple random selection
176+
4. **Efficient data structures** - Optimized locale data
177+
5. **Modern JavaScript** - Uses latest ES features
178+
6. **Tree-shakeable** - Only load what you use
179+
180+
## Contributing
181+
182+
To update benchmarks or add new tests:
183+
184+
1. Edit `packages/benchmarks/src/index.ts`
185+
2. Run `bun run bench` to verify
186+
3. Update this file with new results
187+
188+
## License
189+
190+
MIT

README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,41 @@ nanofaker batch 100 --template user > users.json
333333

334334
See the [CLI documentation](https://nanofaker.stacksjs.org/cli) for complete details.
335335

336+
## Performance Benchmarks
337+
338+
nanofaker is designed for performance. We benchmark against all major JavaScript/TypeScript faker libraries:
339+
340+
**Results Summary:**
341+
-**9 out of 9 benchmarks won** (100% win rate!)
342+
-**6.57x faster than @faker-js/faker** on average
343+
- 🚀 **39.63M ops/s** for city generation
344+
- 📊 **7.97ms** to generate 10,000 complex user objects
345+
346+
### Quick Comparison
347+
348+
| Operation | nanofaker | @faker-js/faker | Speedup |
349+
|-----------|-----------|-----------------|---------|
350+
| Full Name Generation | 31.35M ops/s | 537.95K ops/s | **58x faster** |
351+
| Phone Number Generation | 9.77M ops/s | 2.05M ops/s | **4.8x faster** |
352+
| City Generation | 39.63M ops/s | 779.69K ops/s | **51x faster** |
353+
| Email Generation | 1.96M ops/s | 567.44K ops/s | **3.5x faster** |
354+
| Complex Objects (10k) | 7.97ms | 52.39ms | **6.6x faster** |
355+
356+
### Running Benchmarks
357+
358+
```bash
359+
# Run all benchmarks
360+
bun run bench
361+
362+
# Results are compared against:
363+
# - @faker-js/faker
364+
# - chance
365+
# - casual
366+
# - @ngneat/falso
367+
```
368+
369+
📊 See [BENCHMARKS.md](./BENCHMARKS.md) for detailed results and methodology.
370+
336371
## Testing
337372

338373
```bash

0 commit comments

Comments
 (0)