Skip to content

Commit a368f98

Browse files
committed
docs: refresh benchmark tables; make scenario claims number-driven
Tables regenerated from the current benchmark.js/benchmark2.js runs. The generator now derives the win/concession wording from the actual scenario results instead of hardcoding 'Day.js is faster in Time Operations' — which the current numbers no longer support (kk-date is fastest in every scenario, including Time Operations).
1 parent ed10a9b commit a368f98

3 files changed

Lines changed: 45 additions & 38 deletions

File tree

README.md

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,25 @@
22

33
[![npm version](https://badge.fury.io/js/kk-date.svg)](https://badge.fury.io/js/kk-date)
44
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5-
[![Tests](https://img.shields.io/badge/Tests-523%20passed-brightgreen)](https://github.com/kentkartlab/kk-date)
5+
[![Tests](https://img.shields.io/badge/Tests-585%20passed-brightgreen)](https://github.com/kentkartlab/kk-date)
66

77
A blazing-fast JavaScript date library with intelligent caching, automatic DST detection, and zero-config timezone handling. Perfect for high-performance applications, real-time systems, and data-intensive operations where speed and accuracy matter most.
88

99
## 🌟 Why Choose kk-date?
1010

1111
### Performance & Efficiency *(measured on Node.js 26; reproduced by CI, results vary)*
1212
<!-- BENCH:readme-why -->
13-
- **⚡ Lightning Fast** - Over 40x faster timezone operations than Day.js
14-
- **🚀 ~89% Faster Overall** - Wins most scenarios vs Moment.js, Day.js, and Luxon (Day.js is faster in isolated "Time Operations")
13+
- **⚡ Lightning Fast** - Over 30x faster timezone operations than Day.js
14+
- **🚀 ~96% Faster Overall** - Fastest in every scenario vs Moment.js, Day.js, and Luxon
1515
- **💾 Memory Efficient** - Object pooling + LRU cache eviction keep long-running processes stable
16-
- **⚙️ Smart Caching** - ~59% faster repeated operations with built-in caching
16+
- **⚙️ Smart Caching** - ~24% faster repeated operations with built-in caching
1717
<!-- /BENCH:readme-why -->
1818

1919
### Reliability & Safety
2020
- **🛡️ Fail-Fast Design** - Invalid dates immediately throw errors, preventing silent bugs in production
2121
- **🎯 Type Safety** - Rejects malformed dates instead of returning unexpected results
2222
- **✅ Predictable Behavior** - Never continues with invalid dates, unlike libraries that return "Invalid Date"
23-
- **🔒 Production Tested** - 523 comprehensive tests covering edge cases and DST transitions
23+
- **🔒 Production Tested** - 585 comprehensive tests covering edge cases and DST transitions
2424

2525
### Features & Compatibility
2626
- **🌍 Accurate Timezone Handling** - Fast, DST-aware timezone conversions with perfect accuracy
@@ -415,7 +415,7 @@ console.log(date.format('DD/MM/YYYY')); // 23/08/2024
415415

416416
## 📊 Performance Benchmarks
417417

418-
> **Note:** All performance figures in this README come from our own benchmark suite on Node.js 26 and are **reproduced by CI on every PR** (the "Performance Benchmarks" job runs `benchmark.js` + `benchmark2.js` and uploads the results). They are **not guarantees** — results vary by workload, hardware, Node version, and caching. Reproduce locally with `node benchmark.js` / `node benchmark2.js`. kk-date wins most scenarios but not all (e.g. Day.js is faster in isolated "Time Operations").
418+
> **Note:** All performance figures in this README come from our own benchmark suite on Node.js 26 and are **reproduced by CI on every PR** (the "Performance Benchmarks" job runs `benchmark.js` + `benchmark2.js` and uploads the results). They are **not guarantees** — results vary by workload, hardware, Node version, and caching. Reproduce locally with `node benchmark.js` / `node benchmark2.js`.
419419
420420
### Real-World Sequential Operations (1000 days, 100 operations/day)
421421

@@ -431,23 +431,23 @@ node benchmark2.js
431431
<!-- BENCH:readme-seq -->
432432
| Operation | kk-date | Moment.js | Day.js | Luxon | vs Fastest Competitor |
433433
|-----------|---------|-----------|--------|-------|-----------------------|
434-
| **Date Creation & Formatting** | **159ms** | 1207ms | 822ms | 1055ms | **~417% faster** than Day.js |
435-
| **Time Operations** | **460ms** | 1367ms | 612ms | 2827ms | **~33% faster** than Day.js |
436-
| **Timezone Conversions** | **445ms** | 2925ms | 18772ms | 4312ms | **~557% faster** than Moment |
437-
| **Complex Operations** | **368ms** | 2621ms | 1398ms | 3161ms | **~280% faster** than Day.js |
434+
| **Date Creation & Formatting** | **286ms** | 2109ms | 1336ms | 1976ms | **~368% faster** than Day.js |
435+
| **Time Operations** | **397ms** | 2448ms | 1103ms | 4704ms | **~178% faster** than Day.js |
436+
| **Timezone Conversions** | **942ms** | 5595ms | 35194ms | 8545ms | **~494% faster** than Moment |
437+
| **Complex Operations** | **541ms** | 4422ms | 2556ms | 5611ms | **~373% faster** than Day.js |
438438
<!-- /BENCH:readme-seq -->
439439

440440
### Overall Performance Summary
441441

442-
kk-date wins the overall sequential run, though Day.js is faster in the isolated "Time Operations" scenario above.
442+
kk-date wins the overall sequential run and every individual scenario above.
443443

444444
<!-- BENCH:readme-overall -->
445445
| Library | Total Time | Operations/sec | Performance |
446446
|---------|------------|---------------|-------------|
447-
| **kk-date** | **1.43s** | **279,296 ops/sec** | 🏆 **Winner** |
448-
| Moment.js | 8.12s | 49,255 ops/sec | ~467% slower |
449-
| Luxon | 11.36s | 35,226 ops/sec | ~693% slower |
450-
| Day.js | 21.60s | 18,515 ops/sec | **~1408% slower** |
447+
| **kk-date** | **2.17s** | **184,725 ops/sec** | 🏆 **Winner** |
448+
| Moment.js | 14.57s | 27,447 ops/sec | ~573% slower |
449+
| Luxon | 20.84s | 19,197 ops/sec | ~862% slower |
450+
| Day.js | 40.19s | 9,953 ops/sec | **~1756% slower** |
451451
<!-- /BENCH:readme-overall -->
452452

453453
### Memory & Bundle Size
@@ -457,10 +457,10 @@ Net heap delta after creating 100,000 date instances (from `node benchmark.js`).
457457
<!-- BENCH:readme-memory -->
458458
| Library | Heap Δ / 100k instances* | Bundle Size | DST Support |
459459
|---------|--------------------------|-------------|-------------|
460-
| **kk-date** | ~+7 MB | **15 KB** | **Built-in** |
461-
| Moment.js | ~+16 MB | 297 KB | Plugin required |
462-
| Day.js | ~-4 MB* | 18.5 KB | Plugin required |
463-
| Luxon | ~+5 MB | 71 KB | Built-in |
460+
| **kk-date** | ~+1 MB | **15 KB** | **Built-in** |
461+
| Moment.js | ~-3 MB* | 297 KB | Plugin required |
462+
| Day.js | ~-1 MB* | 18.5 KB | Plugin required |
463+
| Luxon | ~-4 MB* | 71 KB | Built-in |
464464
<!-- /BENCH:readme-memory -->
465465

466466
<sub>* GC-timing artifact — varies run-to-run and can be negative for multiple libraries; reproduce with `node benchmark.js`.</sub>
@@ -479,8 +479,8 @@ console.log((after - before) / 1024 / 1024, 'MB'); // GC-dependent; can be negat
479479

480480
**Without Cache vs With Cache (representative run):**
481481
<!-- BENCH:readme-cache -->
482-
- **~59% faster** repeated operations when cache is enabled
483-
- Average operation time: ~78ms~32ms with cache
482+
- **~24% faster** repeated operations when cache is enabled
483+
- Average operation time: ~52ms~40ms with cache
484484
- Cache hit ratio: **100%** for repeated operations
485485
<!-- /BENCH:readme-cache -->
486486
- Memory overhead: minimal (caches are LRU-capped at 10,000 entries)
@@ -500,14 +500,14 @@ kk_date.caching({ status: true, defaultTtl: 3600 });
500500
### Key Performance Advantages
501501

502502
<!-- BENCH:readme-advantages -->
503-
- **~89% faster** than the average of competing libraries (comprehensive benchmark)
504-
- **🚀 up to ~98% faster** in timezone operations (critical for global apps)
503+
- **~96% faster** than the average of competing libraries (comprehensive benchmark)
504+
- **🚀 up to ~97% faster** in timezone operations (critical for global apps)
505505
- **📊 Big-data ready** - efficient for bulk/1M-operation workloads
506506
- **💾 Stable memory** - object pooling + LRU eviction; net heap delta is GC-dependent (often negative)
507-
- **⚙️ ~59% boost** with smart caching enabled
508-
- **🌍 Over 40x faster** (≈4100%) than Day.js in timezone conversions
507+
- **⚙️ ~24% boost** with smart caching enabled
508+
- **🌍 Over 30x faster** (≈3600%) than Day.js in timezone conversions
509509
<!-- /BENCH:readme-advantages -->
510-
- **✅ Production tested** with 523 comprehensive tests
510+
- **✅ Production tested** with 585 comprehensive tests
511511

512512
## 🤝 Contributing
513513

docs/PERFORMANCE.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -384,22 +384,22 @@ node benchmark2.js # Sequential operations benchmark
384384
<!-- BENCH:perf-seq -->
385385
| Operation | kk-date | Moment.js | Day.js | Luxon | vs Fastest Competitor |
386386
|-----------|---------|-----------|--------|-------|-----------------------|
387-
| **Date Creation & Formatting** | **159ms** | 1207ms | 822ms | 1055ms | **~417% faster** than Day.js |
388-
| **Time Operations** | **460ms** | 1367ms | 612ms | 2827ms | **~33% faster** than Day.js |
389-
| **Timezone Conversions** | **445ms** | 2925ms | 18772ms | 4312ms | **~557% faster** than Moment |
390-
| **Complex Operations** | **368ms** | 2621ms | 1398ms | 3161ms | **~280% faster** than Day.js |
391-
| **Overall** | **1.43s** | 8.12s | 21.60s | 11.36s | **~15.1x faster** than Day.js |
387+
| **Date Creation & Formatting** | **286ms** | 2109ms | 1336ms | 1976ms | **~368% faster** than Day.js |
388+
| **Time Operations** | **397ms** | 2448ms | 1103ms | 4704ms | **~178% faster** than Day.js |
389+
| **Timezone Conversions** | **942ms** | 5595ms | 35194ms | 8545ms | **~494% faster** than Moment |
390+
| **Complex Operations** | **541ms** | 4422ms | 2556ms | 5611ms | **~373% faster** than Day.js |
391+
| **Overall** | **2.17s** | 14.57s | 40.19s | 20.84s | **~18.6x faster** than Day.js |
392392
<!-- /BENCH:perf-seq -->
393393

394394
#### Key Performance Metrics
395395

396396
*Measured in our benchmark suite on Node.js 26 and reproduced by CI on every PR (the "Performance Benchmarks" job). These are not guarantees — results vary by workload, hardware, and Node version. Reproduce them with `node benchmark.js` / `node benchmark2.js`.*
397397

398398
<!-- BENCH:perf-metrics -->
399-
- **~89% faster** than the average of competing libraries (comprehensive benchmark)
400-
- **up to ~98% faster** in timezone operations
401-
- **~59% faster** with caching enabled
402-
- **kk-date does not win every scenario** — Day.js is faster in isolated "Time Operations"
399+
- **~96% faster** than the average of competing libraries (comprehensive benchmark)
400+
- **up to ~97% faster** in timezone operations
401+
- **~24% faster** with caching enabled
402+
- **kk-date wins every scenario** in the current benchmark run
403403
- **Net memory delta is GC-dependent** (often negative for several libraries); stability comes from object pooling + LRU eviction
404404
- **Near-100% cache hit rate** for repeated operations
405405
<!-- /BENCH:perf-metrics -->

scripts/update-benchmark-docs.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,14 +142,19 @@ function derived(seq, comp) {
142142
const tzXfloor = Math.floor(tzX / 10) * 10; // stable "over Nx" (only moves when it crosses a decade)
143143
const tzXpct = round(tzX - 1) * 100; // Day.js takes ~this many % MORE time
144144
const cachePct = round(comp.cache.improvementPct);
145-
return { avgFaster, tzMaxFaster, tzXfloor, tzXpct, cachePct };
145+
// Sequential scenarios where any competitor beats kk-date in THIS run — drives the
146+
// win/concession wording below so the prose can never contradict the tables.
147+
const lostScenarios = SEQ_ORDER.filter((name) => COMPETS.some((c) => seq.scenarios[name][c] < seq.scenarios[name]['kk-date']));
148+
return { avgFaster, tzMaxFaster, tzXfloor, tzXpct, cachePct, lostScenarios };
146149
}
147150

148151
function whyBullets(seq, comp) {
149152
const d = derived(seq, comp);
150153
return [
151154
`- **⚡ Lightning Fast** - Over ${d.tzXfloor}x faster timezone operations than Day.js`,
152-
`- **🚀 ~${d.avgFaster}% Faster Overall** - Wins most scenarios vs Moment.js, Day.js, and Luxon (Day.js is faster in isolated "Time Operations")`,
155+
d.lostScenarios.length
156+
? `- **🚀 ~${d.avgFaster}% Faster Overall** - Wins most scenarios vs Moment.js, Day.js, and Luxon (slower in isolated "${d.lostScenarios.join('", "')}")`
157+
: `- **🚀 ~${d.avgFaster}% Faster Overall** - Fastest in every scenario vs Moment.js, Day.js, and Luxon`,
153158
'- **💾 Memory Efficient** - Object pooling + LRU cache eviction keep long-running processes stable',
154159
`- **⚙️ Smart Caching** - ~${d.cachePct}% faster repeated operations with built-in caching`,
155160
].join('\n');
@@ -173,7 +178,9 @@ function perfMetricsBullets(seq, comp) {
173178
`- **~${d.avgFaster}% faster** than the average of competing libraries (comprehensive benchmark)`,
174179
`- **up to ~${d.tzMaxFaster}% faster** in timezone operations`,
175180
`- **~${d.cachePct}% faster** with caching enabled`,
176-
'- **kk-date does not win every scenario** — Day.js is faster in isolated "Time Operations"',
181+
d.lostScenarios.length
182+
? `- **kk-date does not win every scenario** — slower in isolated "${d.lostScenarios.join('", "')}"`
183+
: '- **kk-date wins every scenario** in the current benchmark run',
177184
'- **Net memory delta is GC-dependent** (often negative for several libraries); stability comes from object pooling + LRU eviction',
178185
'- **Near-100% cache hit rate** for repeated operations',
179186
].join('\n');

0 commit comments

Comments
 (0)