Skip to content

Commit 3b3ae4b

Browse files
committed
improve memoization
1 parent a2d0351 commit 3b3ae4b

File tree

3 files changed

+43
-19
lines changed

3 files changed

+43
-19
lines changed

src/main.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@ if (typeof LIVE_RELOAD !== "undefined" && LIVE_RELOAD) {
1010
}
1111

1212
import { dictionary } from "../dictionary/dictionary.ts";
13+
import { flattenError } from "../misc/misc.ts";
1314
import PROJECT_DATA from "../project_data.json" with { type: "json" };
1415
import { ArrayResultError, isArrayResult } from "./array_result.ts";
1516
import { loadCustomDictionary } from "./dictionary.ts";
1617
import { checkLocalStorage, setIgnoreError } from "./local_storage.ts";
17-
import { flattenError } from "../misc/misc.ts";
1818
import { translate } from "./mod.ts";
19+
import { clearCache } from "./parser/parser_lib.ts";
1920
import { settings } from "./settings.ts";
2021
import {
2122
loadFromElements,
@@ -218,6 +219,7 @@ function main(): void {
218219
confirmButton.addEventListener("click", () => {
219220
loadFromElements();
220221
updateLabel();
222+
clearCache();
221223
settingsDialogBox.close();
222224
});
223225
cancelButton.addEventListener("click", () => {
@@ -269,6 +271,7 @@ function main(): void {
269271
try {
270272
loadCustomDictionary(value);
271273
setIgnoreError(DICTIONARY_KEY, value);
274+
clearCache();
272275
customDictionaryDialogBox.close();
273276
} catch (error) {
274277
const errors = flattenError(error);

src/mod.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { translate as rawTranslate } from "./translator/translator.ts";
88

99
export { ArrayResultError, type ArrayResultOptions } from "./array_result.ts";
1010
export { loadCustomDictionary } from "./dictionary.ts";
11+
export { clearCache } from "./parser/parser_lib.ts";
1112
export {
1213
defaultSettings,
1314
type RedundancySettings,

src/parser/parser_lib.ts

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,63 @@
11
import { assert } from "@std/assert/assert";
2-
import { LruCache } from "@std/cache/lru-cache";
32
import { MemoizationCacheResult, memoize } from "@std/cache/memoize";
43
import { ArrayResult, ArrayResultError } from "../array_result.ts";
54

6-
const CACHE_SIZE = 10;
7-
85
type Source = Readonly<{ source: string; position: number }>;
96
type ParserResult<T> = ArrayResult<Readonly<{ value: T; size: number }>>;
107
type InnerParser<T> = (input: Source) => ParserResult<T>;
118

129
class SourceMemo<T> {
13-
#map: LruCache<string, Map<number, T>> = new LruCache(CACHE_SIZE);
10+
#source = "";
11+
#map: Map<number, T> = new Map();
1412
set(key: Source, value: T): void {
15-
let map = this.#map.get(key.source);
16-
if (map == null) {
17-
const newMap: Map<number, T> = new Map();
18-
this.#map.set(key.source, newMap);
19-
map = newMap;
13+
if (this.#source !== key.source) {
14+
this.#source = key.source;
15+
this.#map = new Map();
2016
}
21-
map.set(key.position, value);
17+
this.#map.set(key.position, value);
2218
}
2319
get(key: Source): undefined | T {
24-
return this.#map.get(key.source)?.get(key.position);
20+
if (this.#source === key.source) {
21+
return this.#map.get(key.position);
22+
} else {
23+
return undefined;
24+
}
2525
}
2626
has(key: Source): boolean {
27-
return this.#map.get(key.source)?.has(key.position) ?? false;
27+
return this.#source === key.source && this.#map.has(key.position);
2828
}
2929
delete(key: Source): void {
30-
this.#map.get(key.source)?.delete(key.position);
30+
if (this.#source === key.source) {
31+
this.#map.delete(key.position);
32+
}
33+
}
34+
clear(): void {
35+
this.#map.clear();
36+
}
37+
}
38+
type SourceMemoResult<T> = SourceMemo<MemoizationCacheResult<ParserResult<T>>>;
39+
40+
const caches: Set<WeakRef<SourceMemo<unknown>>> = new Set();
41+
42+
export function clearCache(): void {
43+
for (const memo of caches) {
44+
const ref = memo.deref();
45+
if (ref == null) {
46+
caches.delete(memo);
47+
} else {
48+
ref.clear();
49+
}
3150
}
3251
}
3352
export class Parser<T> {
3453
readonly rawParser: InnerParser<T>;
3554
constructor(parser: InnerParser<T>) {
36-
this.rawParser = memoize<
37-
InnerParser<T>,
38-
Source,
39-
SourceMemo<MemoizationCacheResult<ParserResult<T>>>
40-
>(parser, { cache: new SourceMemo() });
55+
const cache: SourceMemoResult<T> = new SourceMemo();
56+
caches.add(new WeakRef(cache));
57+
this.rawParser = memoize<InnerParser<T>, Source, SourceMemoResult<T>>(
58+
parser,
59+
{ cache },
60+
);
4161
}
4262
generateParser(): (source: string) => ArrayResult<T> {
4363
return (source) =>

0 commit comments

Comments
 (0)