From eb19a5e866e9fce420f94ee2e76cfcf6763a9bf0 Mon Sep 17 00:00:00 2001 From: Jared Wray Date: Sun, 27 Oct 2024 13:34:57 -0700 Subject: [PATCH 1/2] cacheable - moving back to internal hash on CacheableMemory --- packages/cacheable/src/hash-store.ts | 122 --------------------- packages/cacheable/src/memory.ts | 118 +++++++++++++++++--- packages/cacheable/test/hash-store.test.ts | 18 --- 3 files changed, 105 insertions(+), 153 deletions(-) delete mode 100644 packages/cacheable/src/hash-store.ts delete mode 100644 packages/cacheable/test/hash-store.test.ts diff --git a/packages/cacheable/src/hash-store.ts b/packages/cacheable/src/hash-store.ts deleted file mode 100644 index 942aa99d..00000000 --- a/packages/cacheable/src/hash-store.ts +++ /dev/null @@ -1,122 +0,0 @@ -import {type CacheableStoreItem} from './cacheable-item-types.js'; - -export class CacheableHashStore { - private readonly _hashCache = new Map(); - private readonly _hash0 = new Map(); - private readonly _hash1 = new Map(); - private readonly _hash2 = new Map(); - private readonly _hash3 = new Map(); - private readonly _hash4 = new Map(); - private readonly _hash5 = new Map(); - private readonly _hash6 = new Map(); - private readonly _hash7 = new Map(); - private readonly _hash8 = new Map(); - private readonly _hash9 = new Map(); - - public get size(): number { - return this._hash0.size + this._hash1.size + this._hash2.size + this._hash3.size + this._hash4.size + this._hash5.size + this._hash6.size + this._hash7.size + this._hash8.size + this._hash9.size; - } - - public set(item: CacheableStoreItem) { - this.getStore(item.key).set(item.key, item); - } - - public get(key: string) { - return this.getStore(key).get(key); - } - - public delete(key: string) { - return this.getStore(key).delete(key); - } - - public has(key: string) { - return this.getStore(key).has(key); - } - - public clear() { - this._hash0.clear(); - this._hash1.clear(); - this._hash2.clear(); - this._hash3.clear(); - this._hash4.clear(); - this._hash5.clear(); - this._hash6.clear(); - this._hash7.clear(); - this._hash8.clear(); - this._hash9.clear(); - this._hashCache.clear(); - } - - public concatStores(): Map { - const result = new Map([...this._hash0, ...this._hash1, ...this._hash2, ...this._hash3, ...this._hash4, ...this._hash5, ...this._hash6, ...this._hash7, ...this._hash8, ...this._hash9]); - return result; - } - - public getStore(key: string) { - const hash = this.hashKey(key); - return this.getStoreFromHash(hash); - } - - public getStoreFromHash(hash: number) { - switch (hash) { - case 1: { - return this._hash1; - } - - case 2: { - return this._hash2; - } - - case 3: { - return this._hash3; - } - - case 4: { - return this._hash4; - } - - case 5: { - return this._hash5; - } - - case 6: { - return this._hash6; - } - - case 7: { - return this._hash7; - } - - case 8: { - return this._hash8; - } - - case 9: { - return this._hash9; - } - - default: { - return this._hash0; - } - } - } - - public hashKey(key: string): number { - const cacheHashNumber = this._hashCache.get(key)!; - if (cacheHashNumber) { - return cacheHashNumber; - } - - let hash = 0; - const primeMultiplier = 31; // Use a prime multiplier for better distribution - - for (let i = 0; i < key.length; i++) { - // eslint-disable-next-line unicorn/prefer-code-point - hash = (hash * primeMultiplier) + key.charCodeAt(i); - } - - const result = Math.abs(hash) % 10; // Return a number between 0 and 9 - this._hashCache.set(key, result); - return result; - } -} diff --git a/packages/cacheable/src/memory.ts b/packages/cacheable/src/memory.ts index 15cf0f40..0534acfa 100644 --- a/packages/cacheable/src/memory.ts +++ b/packages/cacheable/src/memory.ts @@ -3,7 +3,6 @@ import {DoublyLinkedList} from './memory-lru.js'; import {shorthandToTime} from './shorthand-time.js'; import {type CacheableStoreItem, type CacheableItem} from './cacheable-item-types.js'; import {hash} from './hash.js'; -import {CacheableHashStore} from './hash-store.js'; /** * @typedef {Object} CacheableMemoryOptions @@ -22,9 +21,18 @@ export type CacheableMemoryOptions = { }; export class CacheableMemory { + private _lru = new DoublyLinkedList(); private readonly _hashCache = new Map(); - private readonly _defaultStore = new CacheableHashStore(); - private readonly _lru = new DoublyLinkedList(); + private readonly _hash0 = new Map(); + private readonly _hash1 = new Map(); + private readonly _hash2 = new Map(); + private readonly _hash3 = new Map(); + private readonly _hash4 = new Map(); + private readonly _hash5 = new Map(); + private readonly _hash6 = new Map(); + private readonly _hash7 = new Map(); + private readonly _hash8 = new Map(); + private readonly _hash9 = new Map(); private _ttl: number | string | undefined; // Turned off by default private _useClone = true; // Turned on by default @@ -126,7 +134,7 @@ export class CacheableMemory { * @returns {number} - The size of the cache */ public get size(): number { - return this._defaultStore.size; + return this._hash0.size + this._hash1.size + this._hash2.size + this._hash3.size + this._hash4.size + this._hash5.size + this._hash6.size + this._hash7.size + this._hash8.size + this._hash9.size; } /** @@ -254,12 +262,12 @@ export class CacheableMemory { } } - store.set({ + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const item = {key, value, expires}; + store.set( key, - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - value, - expires, - }); + item, + ); } /** @@ -353,8 +361,18 @@ export class CacheableMemory { * @returns {void} */ public clear(): void { - this._defaultStore.clear(); + this._hash0.clear(); + this._hash1.clear(); + this._hash2.clear(); + this._hash3.clear(); + this._hash4.clear(); + this._hash5.clear(); + this._hash6.clear(); + this._hash7.clear(); + this._hash8.clear(); + this._hash9.clear(); this._hashCache.clear(); + this._lru = new DoublyLinkedList(); } /** @@ -362,8 +380,82 @@ export class CacheableMemory { * @param {string} key - The key to get the store * @returns {CacheableHashStore} - The store */ - public getStore(key: string): CacheableHashStore { - return this._defaultStore; + public getStore(key: string): Map { + const hash = this.hashKey(key); + return this.getStoreFromHash(hash); + } + + /** + * Get the store based on the hash (internal use) + * @param {number} hash + * @returns {Map} + */ + public getStoreFromHash(hash: number): Map { + switch (hash) { + case 1: { + return this._hash1; + } + + case 2: { + return this._hash2; + } + + case 3: { + return this._hash3; + } + + case 4: { + return this._hash4; + } + + case 5: { + return this._hash5; + } + + case 6: { + return this._hash6; + } + + case 7: { + return this._hash7; + } + + case 8: { + return this._hash8; + } + + case 9: { + return this._hash9; + } + + default: { + return this._hash0; + } + } + } + + /** + * Hash the key (internal use) + * @param key + * @returns {number} from 0 to 9 + */ + public hashKey(key: string): number { + const cacheHashNumber = this._hashCache.get(key)!; + if (cacheHashNumber) { + return cacheHashNumber; + } + + let hash = 0; + const primeMultiplier = 31; // Use a prime multiplier for better distribution + + for (let i = 0; i < key.length; i++) { + // eslint-disable-next-line unicorn/prefer-code-point + hash = (hash * primeMultiplier) + key.charCodeAt(i); + } + + const result = Math.abs(hash) % 10; // Return a number between 0 and 9 + this._hashCache.set(key, result); + return result; } /** @@ -503,7 +595,7 @@ export class CacheableMemory { } private concatStores(): Map { - return this._defaultStore.concatStores(); + return new Map([...this._hash0, ...this._hash1, ...this._hash2, ...this._hash3, ...this._hash4, ...this._hash5, ...this._hash6, ...this._hash7, ...this._hash8, ...this._hash9]); } private setTtl(ttl: number | string | undefined): void { diff --git a/packages/cacheable/test/hash-store.test.ts b/packages/cacheable/test/hash-store.test.ts deleted file mode 100644 index 0ef6e35f..00000000 --- a/packages/cacheable/test/hash-store.test.ts +++ /dev/null @@ -1,18 +0,0 @@ -import {expect, test, describe} from 'vitest'; -import {CacheableHashStore} from '../src/hash-store.js'; - -describe('CacheableHashStore', () => { - test('hash key should be the correct number', () => { - const cache = new CacheableHashStore(); - expect(cache.hashKey('apple')).toBe(0); - expect(cache.hashKey('carrot')).toBe(1); - expect(cache.hashKey('4123')).toBe(2); - expect(cache.hashKey('mouse')).toBe(3); - expect(cache.hashKey('dog')).toBe(4); - expect(cache.hashKey('ice')).toBe(5); - expect(cache.hashKey('jacket')).toBe(6); - expect(cache.hashKey('grape')).toBe(7); - expect(cache.hashKey('house')).toBe(8); - expect(cache.hashKey('banana')).toBe(9); - }); -}); From 68548764ff6fbbcd4e4a180a6c98c3566f56086a Mon Sep 17 00:00:00 2001 From: Jared Wray Date: Sun, 27 Oct 2024 13:37:27 -0700 Subject: [PATCH 2/2] Update memory.ts --- packages/cacheable/src/memory.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cacheable/src/memory.ts b/packages/cacheable/src/memory.ts index 0534acfa..9ca241ce 100644 --- a/packages/cacheable/src/memory.ts +++ b/packages/cacheable/src/memory.ts @@ -387,7 +387,7 @@ export class CacheableMemory { /** * Get the store based on the hash (internal use) - * @param {number} hash + * @param {number} hash * @returns {Map} */ public getStoreFromHash(hash: number): Map { @@ -436,7 +436,7 @@ export class CacheableMemory { /** * Hash the key (internal use) - * @param key + * @param key * @returns {number} from 0 to 9 */ public hashKey(key: string): number {