Comparing version 0.0.721 to 0.0.722
@@ -445,3 +445,3 @@ import { Cache } from './cache'; | ||
console.debug('DWC overlap', dwc['overlapLRU'], dwc['overlapLFU']); | ||
assert(stats.dwc / stats.lru * 100 >>> 0 === 174); | ||
assert(stats.dwc / stats.lru * 100 >>> 0 === 173); | ||
}); | ||
@@ -535,3 +535,3 @@ | ||
console.debug('DWC overlap', dwc['overlapLRU'], dwc['overlapLFU']); | ||
assert(stats.dwc / stats.lru * 100 >>> 0 === 66); | ||
assert(stats.dwc / stats.lru * 100 >>> 0 === 67); | ||
}); | ||
@@ -562,3 +562,3 @@ | ||
assert(stats.dwc / stats.lru * 100 === Infinity); | ||
assert(stats.dwc * 100 / trials >>> 0 === 41); | ||
assert(stats.dwc * 100 / trials >>> 0 === 42); | ||
}); | ||
@@ -631,3 +631,3 @@ | ||
assert(stats.dwc / stats.lru * 100 === Infinity); | ||
assert(stats.dwc * 100 / capacity >>> 0 === 24); | ||
assert(stats.dwc * 100 / capacity >>> 0 === 8); | ||
}); | ||
@@ -675,4 +675,4 @@ | ||
console.debug('DWC overlap', dwc['overlapLRU'], dwc['overlapLFU']); | ||
assert(stats.dwc / stats.lru * 100 >>> 0 === 82); | ||
assert(dwc['LFU'].length * 100 / capacity >>> 0 === 86); | ||
assert(stats.dwc / stats.lru * 100 >>> 0 === 79); | ||
assert(dwc['LFU'].length * 100 / capacity >>> 0 === 88); | ||
}); | ||
@@ -720,4 +720,4 @@ | ||
console.debug('DWC overlap', dwc['overlapLRU'], dwc['overlapLFU']); | ||
assert(stats.dwc / stats.lru * 100 >>> 0 === 39); | ||
assert(dwc['LFU'].length * 100 / capacity >>> 0 === 90); | ||
assert(stats.dwc / stats.lru * 100 >>> 0 === 37); | ||
assert(dwc['LFU'].length * 100 / capacity >>> 0 === 76); | ||
}); | ||
@@ -750,3 +750,3 @@ | ||
console.debug('DWC overlap', dwc['overlapLRU'], dwc['overlapLFU']); | ||
assert(stats.dwc / stats.lru * 100 >>> 0 === 167); | ||
assert(stats.dwc / stats.lru * 100 >>> 0 === 168); | ||
}); | ||
@@ -753,0 +753,0 @@ |
80
cache.ts
@@ -144,5 +144,6 @@ import { max, min, floor, round } from './alias'; | ||
readonly sweep?: { | ||
// Setting 20 is usually better with standard (non-skewed) workloads. | ||
readonly threshold?: number; | ||
readonly ratio?: number; | ||
readonly window?: number; | ||
readonly room?: number; | ||
readonly range?: number; | ||
@@ -182,4 +183,6 @@ readonly shift?: number; | ||
settings.sweep!.threshold!, | ||
settings.sweep!.ratio!, | ||
capacity, | ||
settings.sweep!.window!, | ||
settings.sweep!.room!, | ||
settings.sweep!.range!, | ||
@@ -202,3 +205,5 @@ settings.sweep!.shift!); | ||
threshold: 10, | ||
ratio: 50, | ||
window: 2, | ||
room: 50, | ||
range: 1, | ||
@@ -581,3 +586,7 @@ shift: 2, | ||
this.resource = resource ?? this.settings.resource ?? capacity; | ||
this.sweeper.resize(capacity, this.settings.sweep!.window!, this.settings.sweep!.range!); | ||
this.sweeper.resize( | ||
capacity, | ||
this.settings.sweep!.window!, | ||
this.settings.sweep!.room!, | ||
this.settings.sweep!.range!); | ||
this.ensure(0); | ||
@@ -592,4 +601,6 @@ } | ||
private readonly threshold: number, | ||
private readonly ratio: number, | ||
capacity: number, | ||
private window: number, | ||
private room: number, | ||
private range: number, | ||
@@ -600,17 +611,29 @@ private readonly shift: number, | ||
this.window = round(capacity * window / 100) || 1; | ||
this.room = round(capacity * room / 100) || 1; | ||
this.range = capacity * range / 100; | ||
} | ||
private currHits = 0; | ||
private currMisses = 0; | ||
private prevHits = 0; | ||
private prevMisses = 0; | ||
private slide(): void { | ||
this.prevHits = this.currHits; | ||
this.prevMisses = this.currMisses; | ||
this.currHits = 0; | ||
this.currMisses = 0; | ||
private currWindowHits = 0; | ||
private currWindowMisses = 0; | ||
private prevWindowHits = 0; | ||
private prevWindowMisses = 0; | ||
private slideWindow(): void { | ||
this.prevWindowHits = this.currWindowHits; | ||
this.prevWindowMisses = this.currWindowMisses; | ||
this.currWindowHits = 0; | ||
this.currWindowMisses = 0; | ||
} | ||
private currRoomHits = 0; | ||
private currRoomMisses = 0; | ||
private prevRoomHits = 0; | ||
private prevRoomMisses = 0; | ||
private slideRoom(): void { | ||
this.prevRoomHits = this.currRoomHits; | ||
this.prevRoomMisses = this.currRoomMisses; | ||
this.currRoomHits = 0; | ||
this.currRoomMisses = 0; | ||
} | ||
public hit(): void { | ||
this.active = undefined; | ||
++this.currHits + this.currMisses === this.window && this.slide(); | ||
++this.currWindowHits + this.currWindowMisses === this.window && this.slideWindow(); | ||
++this.currRoomHits + this.currRoomMisses === this.room && this.slideRoom(); | ||
this.processing && !this.isActive() && this.reset(); | ||
@@ -620,16 +643,25 @@ } | ||
this.active = undefined; | ||
this.currHits + ++this.currMisses === this.window && this.slide(); | ||
this.currWindowHits + ++this.currWindowMisses === this.window && this.slideWindow(); | ||
this.currRoomHits + ++this.currRoomMisses === this.room && this.slideRoom(); | ||
} | ||
private active?: boolean; | ||
public isActive(): boolean { | ||
if (this.prevHits === 0 && this.prevMisses === 0) return false; | ||
return this.active ??= this.ratio() < this.threshold; | ||
if (this.threshold === 0) return false; | ||
if (this.prevWindowHits === 0 && this.prevWindowMisses === 0) return false; | ||
return this.active ??= this.ratioWindow() < max(this.ratioRoom() * this.ratio / 100, this.threshold); | ||
} | ||
private ratio(): number { | ||
private ratioWindow(): number { | ||
return ratio( | ||
this.window, | ||
[this.currHits, this.prevHits], | ||
[this.currMisses, this.prevMisses], | ||
[this.currWindowHits, this.prevWindowHits], | ||
[this.currWindowMisses, this.prevWindowMisses], | ||
0); | ||
} | ||
private ratioRoom(): number { | ||
return ratio( | ||
this.room, | ||
[this.currRoomHits, this.prevRoomHits], | ||
[this.currRoomMisses, this.prevRoomMisses], | ||
0); | ||
} | ||
private processing = false; | ||
@@ -697,4 +729,6 @@ private direction = true; | ||
assert(!this.processing); | ||
this.slide(); | ||
this.slide(); | ||
this.slideWindow(); | ||
this.slideWindow(); | ||
this.slideRoom(); | ||
this.slideRoom(); | ||
assert(!this.isActive()); | ||
@@ -705,6 +739,8 @@ } | ||
} | ||
public resize(capacity: number, window: number, range: number): void { | ||
public resize(capacity: number, window: number, room: number, range: number): void { | ||
this.window = round(capacity * window / 100) || 1; | ||
this.room = round(capacity * room / 100) || 1; | ||
this.range = capacity * range / 100; | ||
this.currHits + this.currMisses >= this.window && this.slide(); | ||
this.currWindowHits + this.currWindowMisses >= this.window && this.slideWindow(); | ||
this.currRoomHits + this.currRoomMisses >= this.room && this.slideRoom(); | ||
this.active = undefined; | ||
@@ -711,0 +747,0 @@ } |
{ | ||
"name": "spica", | ||
"version": "0.0.721", | ||
"version": "0.0.722", | ||
"description": "Supervisor, Coroutine, Channel, select, AtomicPromise, Cancellation, Cache, List, Queue, Stack, and some utils.", | ||
@@ -60,3 +60,3 @@ "private": false, | ||
"@types/yallist": "4.0.1", | ||
"@typescript-eslint/parser": "^5.59.0", | ||
"@typescript-eslint/parser": "^5.59.1", | ||
"babel-loader": "^9.1.2", | ||
@@ -66,7 +66,7 @@ "babel-plugin-unassert": "^3.2.0", | ||
"concurrently": "^8.0.1", | ||
"eslint": "^8.38.0", | ||
"eslint": "^8.39.0", | ||
"eslint-plugin-redos": "^4.4.5", | ||
"eslint-webpack-plugin": "^4.0.1", | ||
"glob": "^10.2.1", | ||
"karma": "^6.4.1", | ||
"glob": "^10.2.2", | ||
"karma": "^6.4.2", | ||
"karma-chrome-launcher": "^3.2.0", | ||
@@ -77,3 +77,3 @@ "karma-coverage": "^2.2.0", | ||
"karma-power-assert": "^1.0.0", | ||
"lru-cache": "^9.1.0", | ||
"lru-cache": "^9.1.1", | ||
"mocha": "^10.2.0", | ||
@@ -83,3 +83,3 @@ "npm-check-updates": "^16.10.9", | ||
"typescript": "5.0.4", | ||
"webpack": "^5.80.0", | ||
"webpack": "^5.81.0", | ||
"webpack-cli": "^5.0.2", | ||
@@ -86,0 +86,0 @@ "webpack-merge": "^5.8.0", |
@@ -445,3 +445,3 @@ import { Cache } from './cache'; | ||
console.debug('DWC overlap', dwc['overlapLRU'], dwc['overlapLFU']); | ||
assert(stats.dwc / stats.lru * 100 >>> 0 === 174); | ||
assert(stats.dwc / stats.lru * 100 >>> 0 === 173); | ||
}); | ||
@@ -535,3 +535,3 @@ | ||
console.debug('DWC overlap', dwc['overlapLRU'], dwc['overlapLFU']); | ||
assert(stats.dwc / stats.lru * 100 >>> 0 === 66); | ||
assert(stats.dwc / stats.lru * 100 >>> 0 === 67); | ||
}); | ||
@@ -562,3 +562,3 @@ | ||
assert(stats.dwc / stats.lru * 100 === Infinity); | ||
assert(stats.dwc * 100 / trials >>> 0 === 41); | ||
assert(stats.dwc * 100 / trials >>> 0 === 42); | ||
}); | ||
@@ -631,3 +631,3 @@ | ||
assert(stats.dwc / stats.lru * 100 === Infinity); | ||
assert(stats.dwc * 100 / capacity >>> 0 === 24); | ||
assert(stats.dwc * 100 / capacity >>> 0 === 8); | ||
}); | ||
@@ -675,4 +675,4 @@ | ||
console.debug('DWC overlap', dwc['overlapLRU'], dwc['overlapLFU']); | ||
assert(stats.dwc / stats.lru * 100 >>> 0 === 82); | ||
assert(dwc['LFU'].length * 100 / capacity >>> 0 === 86); | ||
assert(stats.dwc / stats.lru * 100 >>> 0 === 79); | ||
assert(dwc['LFU'].length * 100 / capacity >>> 0 === 88); | ||
}); | ||
@@ -720,4 +720,4 @@ | ||
console.debug('DWC overlap', dwc['overlapLRU'], dwc['overlapLFU']); | ||
assert(stats.dwc / stats.lru * 100 >>> 0 === 39); | ||
assert(dwc['LFU'].length * 100 / capacity >>> 0 === 90); | ||
assert(stats.dwc / stats.lru * 100 >>> 0 === 37); | ||
assert(dwc['LFU'].length * 100 / capacity >>> 0 === 76); | ||
}); | ||
@@ -750,3 +750,3 @@ | ||
console.debug('DWC overlap', dwc['overlapLRU'], dwc['overlapLFU']); | ||
assert(stats.dwc / stats.lru * 100 >>> 0 === 167); | ||
assert(stats.dwc / stats.lru * 100 >>> 0 === 168); | ||
}); | ||
@@ -753,0 +753,0 @@ |
@@ -144,5 +144,6 @@ import { max, min, floor, round } from './alias'; | ||
readonly sweep?: { | ||
// Setting 20 is usually better with standard (non-skewed) workloads. | ||
readonly threshold?: number; | ||
readonly ratio?: number; | ||
readonly window?: number; | ||
readonly room?: number; | ||
readonly range?: number; | ||
@@ -182,4 +183,6 @@ readonly shift?: number; | ||
settings.sweep!.threshold!, | ||
settings.sweep!.ratio!, | ||
capacity, | ||
settings.sweep!.window!, | ||
settings.sweep!.room!, | ||
settings.sweep!.range!, | ||
@@ -202,3 +205,5 @@ settings.sweep!.shift!); | ||
threshold: 10, | ||
ratio: 50, | ||
window: 2, | ||
room: 50, | ||
range: 1, | ||
@@ -581,3 +586,7 @@ shift: 2, | ||
this.resource = resource ?? this.settings.resource ?? capacity; | ||
this.sweeper.resize(capacity, this.settings.sweep!.window!, this.settings.sweep!.range!); | ||
this.sweeper.resize( | ||
capacity, | ||
this.settings.sweep!.window!, | ||
this.settings.sweep!.room!, | ||
this.settings.sweep!.range!); | ||
this.ensure(0); | ||
@@ -592,4 +601,6 @@ } | ||
private readonly threshold: number, | ||
private readonly ratio: number, | ||
capacity: number, | ||
private window: number, | ||
private room: number, | ||
private range: number, | ||
@@ -600,17 +611,29 @@ private readonly shift: number, | ||
this.window = round(capacity * window / 100) || 1; | ||
this.room = round(capacity * room / 100) || 1; | ||
this.range = capacity * range / 100; | ||
} | ||
private currHits = 0; | ||
private currMisses = 0; | ||
private prevHits = 0; | ||
private prevMisses = 0; | ||
private slide(): void { | ||
this.prevHits = this.currHits; | ||
this.prevMisses = this.currMisses; | ||
this.currHits = 0; | ||
this.currMisses = 0; | ||
private currWindowHits = 0; | ||
private currWindowMisses = 0; | ||
private prevWindowHits = 0; | ||
private prevWindowMisses = 0; | ||
private slideWindow(): void { | ||
this.prevWindowHits = this.currWindowHits; | ||
this.prevWindowMisses = this.currWindowMisses; | ||
this.currWindowHits = 0; | ||
this.currWindowMisses = 0; | ||
} | ||
private currRoomHits = 0; | ||
private currRoomMisses = 0; | ||
private prevRoomHits = 0; | ||
private prevRoomMisses = 0; | ||
private slideRoom(): void { | ||
this.prevRoomHits = this.currRoomHits; | ||
this.prevRoomMisses = this.currRoomMisses; | ||
this.currRoomHits = 0; | ||
this.currRoomMisses = 0; | ||
} | ||
public hit(): void { | ||
this.active = undefined; | ||
++this.currHits + this.currMisses === this.window && this.slide(); | ||
++this.currWindowHits + this.currWindowMisses === this.window && this.slideWindow(); | ||
++this.currRoomHits + this.currRoomMisses === this.room && this.slideRoom(); | ||
this.processing && !this.isActive() && this.reset(); | ||
@@ -620,16 +643,25 @@ } | ||
this.active = undefined; | ||
this.currHits + ++this.currMisses === this.window && this.slide(); | ||
this.currWindowHits + ++this.currWindowMisses === this.window && this.slideWindow(); | ||
this.currRoomHits + ++this.currRoomMisses === this.room && this.slideRoom(); | ||
} | ||
private active?: boolean; | ||
public isActive(): boolean { | ||
if (this.prevHits === 0 && this.prevMisses === 0) return false; | ||
return this.active ??= this.ratio() < this.threshold; | ||
if (this.threshold === 0) return false; | ||
if (this.prevWindowHits === 0 && this.prevWindowMisses === 0) return false; | ||
return this.active ??= this.ratioWindow() < max(this.ratioRoom() * this.ratio / 100, this.threshold); | ||
} | ||
private ratio(): number { | ||
private ratioWindow(): number { | ||
return ratio( | ||
this.window, | ||
[this.currHits, this.prevHits], | ||
[this.currMisses, this.prevMisses], | ||
[this.currWindowHits, this.prevWindowHits], | ||
[this.currWindowMisses, this.prevWindowMisses], | ||
0); | ||
} | ||
private ratioRoom(): number { | ||
return ratio( | ||
this.room, | ||
[this.currRoomHits, this.prevRoomHits], | ||
[this.currRoomMisses, this.prevRoomMisses], | ||
0); | ||
} | ||
private processing = false; | ||
@@ -697,4 +729,6 @@ private direction = true; | ||
assert(!this.processing); | ||
this.slide(); | ||
this.slide(); | ||
this.slideWindow(); | ||
this.slideWindow(); | ||
this.slideRoom(); | ||
this.slideRoom(); | ||
assert(!this.isActive()); | ||
@@ -705,6 +739,8 @@ } | ||
} | ||
public resize(capacity: number, window: number, range: number): void { | ||
public resize(capacity: number, window: number, room: number, range: number): void { | ||
this.window = round(capacity * window / 100) || 1; | ||
this.room = round(capacity * room / 100) || 1; | ||
this.range = capacity * range / 100; | ||
this.currHits + this.currMisses >= this.window && this.slide(); | ||
this.currWindowHits + this.currWindowMisses >= this.window && this.slideWindow(); | ||
this.currRoomHits + this.currRoomMisses >= this.room && this.slideRoom(); | ||
this.active = undefined; | ||
@@ -711,0 +747,0 @@ } |
@@ -34,3 +34,3 @@ const path = require('path'); | ||
}, | ||
entry: glob.sync('./{src,test}/**/*.ts', { absolute: true }), | ||
entry: glob.sync('./{src,test}/**/*.ts', { absolute: true }).sort(), | ||
output: { | ||
@@ -80,3 +80,3 @@ filename: 'index.js', | ||
return merge(config, { | ||
entry: glob.sync('./!(node_modules)/**/*.ts', { absolute: true }), | ||
entry: glob.sync('./!(node_modules)/**/*.ts', { absolute: true }).sort(), | ||
plugins: [ | ||
@@ -114,3 +114,3 @@ new ESLintPlugin({ | ||
// ignore: './**/*.test.ts', | ||
// }).map(path => [path.match(/[\w.]+(?=\.)/)[0], path])), | ||
// }).map(path => [path.match(/[\w.]+(?=\.)/)[0], path])).sort(), | ||
// output: { | ||
@@ -117,0 +117,0 @@ // filename: '[name].js', |
1153700
32262