Backporting a bunch of optimizations from db-only branch

This commit is contained in:
Zef Hemel
2024-01-13 17:30:15 +01:00
parent 509ece91f0
commit bf1eb03129
24 changed files with 264 additions and 104 deletions
+8 -5
View File
@@ -5,16 +5,19 @@ import { LimitedMap } from "./limited_map.ts";
Deno.test("limited map", async () => {
const mp = new LimitedMap<string>(3);
mp.set("a", "a");
mp.set("b", "b");
mp.set("b", "b", 5);
mp.set("c", "c");
await sleep(2);
assertEquals(mp.get("a"), "a");
await sleep(2);
assertEquals(mp.get("b"), "b");
await sleep(2);
assertEquals(mp.get("c"), "c");
// Drops the first key
mp.set("d", "d");
await sleep(2);
// console.log(mp.toJSON());
assertEquals(mp.get("a"), undefined);
await sleep(10);
// "b" should have been dropped
assertEquals(mp.get("b"), undefined);
assertEquals(mp.get("c"), "c");
console.log(mp.toJSON());
});
+29 -16
View File
@@ -1,20 +1,36 @@
type LimitedMapRecord<V> = Record<string, { value: V; la: number }>;
type LimitedMapRecord<V> = { value: V; la: number };
export class LimitedMap<V> {
constructor(private maxSize: number, private map: LimitedMapRecord<V> = {}) {
private map: Map<string, LimitedMapRecord<V>>;
constructor(
private maxSize: number,
initialJson: Record<string, LimitedMapRecord<V>> = {},
) {
this.map = new Map(Object.entries(initialJson));
}
set(key: string, value: V) {
if (Object.keys(this.map).length >= this.maxSize) {
/**
* @param key
* @param value
* @param ttl time to live (in ms)
*/
set(key: string, value: V, ttl?: number) {
if (ttl) {
setTimeout(() => {
this.map.delete(key);
}, ttl);
}
if (this.map.size >= this.maxSize) {
// Remove the oldest key before adding a new one
const oldestKey = this.getOldestKey();
delete this.map[oldestKey!];
this.map.delete(oldestKey!);
}
this.map[key] = { value, la: Date.now() };
this.map.set(key, { value, la: Date.now() });
}
get(key: string): V | undefined {
const entry = this.map[key];
const entry = this.map.get(key);
if (entry) {
// Update the last accessed timestamp
entry.la = Date.now();
@@ -24,24 +40,21 @@ export class LimitedMap<V> {
}
remove(key: string) {
delete this.map[key];
this.map.delete(key);
}
toJSON() {
return this.map;
return Object.fromEntries(this.map.entries());
}
private getOldestKey(): string | undefined {
let oldestKey: string | undefined;
let oldestTimestamp: number | undefined;
for (const key in this.map) {
if (Object.prototype.hasOwnProperty.call(this.map, key)) {
const entry = this.map[key];
if (!oldestTimestamp || entry.la < oldestTimestamp) {
oldestKey = key;
oldestTimestamp = entry.la;
}
for (const [key, entry] of this.map.entries()) {
if (!oldestTimestamp || entry.la < oldestTimestamp) {
oldestKey = key;
oldestTimestamp = entry.la;
}
}