UNPKG

spica

Version:

Supervisor, Coroutine, Channel, select, AtomicPromise, Cancellation, Cache, List, Queue, Stack, and some utils.

245 lines (227 loc) 7.64 kB
import { TLRU } from './tlru.clock'; import { LRU } from './lru'; import { xorshift } from './random'; import zipfian from 'zipfian-integer'; describe('Unit: lib/tlru.clock', () => { describe('TLRU-Clock', () => { it('basic', function () { { const cache = new TLRU<number, 1>(4, 1, 0, true); for (const i of [0, 1, 2, 3, 4, 5, 6, 7]) { cache.get(i) ?? cache.add(i, 1); } assert.deepStrictEqual( [...cache].map(t => t[0]), [7, 6, 5, 4]); } { const cache = new TLRU<number, 1>(4, 1, 0, false); for (const i of [0, 1, 2, 3, 4, 5, 6, 7]) { cache.get(i) ?? cache.add(i, 1); } assert.deepStrictEqual( [...cache].map(t => t[0]), [7, 6, 5, 4]); } { const cache = new TLRU<number, 1>(4, 1, 0, true); for (const i of [0, 0, 1, 2, 3, 4, 5, 6, 7]) { cache.get(i) ?? cache.add(i, 1); } assert.deepStrictEqual( [...cache].map(t => t[0]), [3, 2, 6, 7]); } { const cache = new TLRU<number, 1>(4, 1, 0, false); for (const i of [0, 0, 1, 2, 3, 4, 5, 6, 7]) { cache.get(i) ?? cache.add(i, 1); } assert.deepStrictEqual( [...cache].map(t => t[0]), [3, 2, 6, 7]); } { const cache = new TLRU<number, 1>(4, 1, 0, true); for (const i of [0, 1, 2, 3, 3, 4, 5, 6, 7, 8]) { cache.get(i) ?? cache.add(i, 1); } assert.deepStrictEqual( [...cache].map(t => t[0]), [7, 3, 6, 8]); } { const cache = new TLRU<number, 1>(4, 1, 0, false); for (const i of [0, 1, 2, 3, 3, 4, 5, 6, 7, 8]) { cache.get(i) ?? cache.add(i, 1); } assert.deepStrictEqual( [...cache].map(t => t[0]), [7, 6, 5, 8]); } { const cache = new TLRU<number, 1>(4, 1, 0, true); for (const i of [0, 1, 2, 3, 4, 4, 5, 6, 7, 8]) { cache.get(i) ?? cache.add(i, 1); } assert.deepStrictEqual( [...cache].map(t => t[0]), [8, 4, 7, 6]); } { const cache = new TLRU<number, 1>(4, 1, 0, false); for (const i of [0, 1, 2, 3, 4, 4, 5, 6, 7, 8]) { cache.get(i) ?? cache.add(i, 1); } assert.deepStrictEqual( [...cache].map(t => t[0]), [8, 7, 6, 5]); } { const cache = new TLRU<number, 1>(4, 1, 0, true); for (const i of [0, 1, 2, 3, 4, 5, 6, 6, 7, 8, 9]) { cache.get(i) ?? cache.add(i, 1); } assert.deepStrictEqual( [...cache].map(t => t[0]), [8, 6, 7, 9]); } { const cache = new TLRU<number, 1>(4, 1, 0, false); for (const i of [0, 1, 2, 3, 4, 5, 6, 6, 7, 8, 9]) { cache.get(i) ?? cache.add(i, 1); } assert.deepStrictEqual( [...cache].map(t => t[0]), [8, 7, 5, 9]); } { const cache = new TLRU<number, 1>(4, 1, 0, true); for (const i of [0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9]) { cache.get(i) ?? cache.add(i, 1); } assert.deepStrictEqual( [...cache].map(t => t[0]), [7, 6, 9, 8]); } { const cache = new TLRU<number, 1>(4, 1, 0, false); for (const i of [0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9]) { cache.get(i) ?? cache.add(i, 1); } assert.deepStrictEqual( [...cache].map(t => t[0]), [7, 6, 9, 8]); } { const cache = new TLRU<number, 1>(4, 100, 0, true); for (const i of [0, 1, 2, 2, 3, 3, 4, 5, 6, 7, 8, 9]) { cache.get(i) ?? cache.add(i, 1); } assert.deepStrictEqual( [...cache].map(t => t[0]), [7, 3, 9, 8]); } { const cache = new TLRU<number, 1>(4, 100, 0, false); for (const i of [0, 1, 2, 2, 3, 3, 4, 5, 6, 7, 8, 9]) { cache.get(i) ?? cache.add(i, 1); } assert.deepStrictEqual( [...cache].map(t => t[0]), [7, 6, 9, 8]); } }); it('order', function () { const capacity = 4; const cache = new TLRU<number, 1>(capacity); for (let i = 0; i < capacity; ++i) { cache.add(~i, 1); } for (const i of [1, 2, 3, 3, 2, 4]) { cache.get(i) ?? cache.add(i, 1); } assert.deepStrictEqual( [...cache].map(t => t[0]), [2, 3, 4, 1]); }); for (let i = 0; i < 1000; ++i) it(`verify ${i}`, function () { this.timeout(10 * 1e3); const capacity = 4; const cache = new TLRU<number, number>(capacity, i % 3, (i % 4 + 99) % 100, i % 2 === 0); const trials = capacity * 1000; const random = xorshift.random(i + 1); for (let i = 0; i < trials; ++i) { const key = random() * capacity * 2 | 0; if (cache.has(key)) { assert(cache.get(key) === ~key); } else { cache.add(key, ~key); } } assert(cache.length === capacity); }); class Stats { trc = 0; lru = 0; } it('even 100', function () { this.timeout(10 * 1e3); const capacity = 100; const trc = new TLRU<number, 1>(capacity); const lru = new LRU<number, 1>(capacity); const trials = capacity * 1000; const random = xorshift.random(1); const stats = new Stats(); for (let i = 0; i < trials; ++i) { const key = random() * capacity * 10 | 0; stats.trc += trc.get(key) ?? +trc.set(key, 1) & 0; stats.lru += lru.get(key) ?? +lru.set(key, 1) & 0; } console.debug('TLRU-Clock even 100'); console.debug('LRU hits', stats.lru); console.debug('TRC hits', stats.trc); console.debug('TRC / LRU hit ratio', `${stats.trc / stats.lru * 100 | 0}%`); assert(stats.trc / stats.lru * 100 >>> 0 === 99); }); it('zipf 100', function () { this.timeout(10 * 1e3); const capacity = 100; const trc = new TLRU<number, 1>(capacity); const lru = new LRU<number, 1>(capacity); const trials = capacity * 1000; const random = zipfian(1, capacity * 1e3, 0.8, xorshift.random(1)); const stats = new Stats(); for (let i = 0; i < trials; ++i) { const key = random(); stats.trc += trc.get(key) ?? +trc.set(key, 1) & 0; stats.lru += lru.get(key) ?? +lru.set(key, 1) & 0; } console.debug('TLRU-Clock zipf 100'); console.debug('LRU hits', stats.lru); console.debug('TRC hits', stats.trc); console.debug('TRC / LRU hit ratio', `${stats.trc / stats.lru * 100 | 0}%`); assert(stats.trc / stats.lru * 100 >>> 0 === 166); }); it('zipf 1,000', function () { this.timeout(60 * 1e3); const capacity = 1000; const trc = new TLRU<number, 1>(capacity); const lru = new LRU<number, 1>(capacity); const trials = capacity * 100; const random = zipfian(1, capacity * 1e3, 0.8, xorshift.random(1)); const stats = new Stats(); for (let i = 0; i < trials; ++i) { const key = random(); stats.trc += trc.get(key) ?? +trc.set(key, 1) & 0; stats.lru += lru.get(key) ?? +lru.set(key, 1) & 0; } console.debug('TLRU-Clock zipf 1000'); console.debug('LRU hits', stats.lru); console.debug('TRC hits', stats.trc); console.debug('TRC / LRU hit ratio', `${stats.trc / stats.lru * 100 | 0}%`); assert(stats.trc / stats.lru * 100 >>> 0 === 145); }); }); });