From a0b06d8794d33f9a4992e349e7b32c91c501cf8a Mon Sep 17 00:00:00 2001 From: SukkaW Date: Thu, 2 May 2024 08:17:46 +0800 Subject: [PATCH] Perf: reduce comparision in domain sorting --- Build/lib/stable-sort-domain.ts | 65 +++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 12 deletions(-) diff --git a/Build/lib/stable-sort-domain.ts b/Build/lib/stable-sort-domain.ts index 012927e06..50944d422 100644 --- a/Build/lib/stable-sort-domain.ts +++ b/Build/lib/stable-sort-domain.ts @@ -1,6 +1,41 @@ import type { PublicSuffixList } from '@gorhill/publicsuffixlist'; import { createCachedGorhillGetDomain } from './cached-tld-parse'; +class TwoKeyCache { + private cache: Map>; + public hitCount = 0; + + constructor() { + this.cache = new Map(); + } + + apply(a: string, b: string, fn: (a: string, b: string) => number): number { + let r = this.get(a, b); + if (r !== undefined) { + this.hitCount++; + return r; + } + + r = fn(a, b); + this.set(a, b, r); + this.set(b, a, -1 * r); + return r; + } + + private get(a: string, b: string): number | undefined { + return this.cache.get(a)?.get(b); + } + + private set(a: string, b: string, value: number): void { + let innerCache = this.cache.get(a); + if (!innerCache) { + innerCache = new Map(); + this.cache.set(a, innerCache); + } + innerCache.set(b, value); + } +} + const compare = (a: string | null, b: string | null) => { if (a === b) return 0; if (b == null) { @@ -12,17 +47,19 @@ const compare = (a: string | null, b: string | null) => { const aLen = a.length; const r = aLen - b.length; - if (r > 0) { - return 1; - } - if (r < 0) { - return -1; - } + // if (r > 0) { + // return 1; + // } + // if (r < 0) { + // return -1; + // } + if (r !== 0) return r; for (let i = 0; i < aLen; i++) { - if (b[i] == null) { - return 1; - } + // if (!b[i]) { + // return 1; + // } + // Since aLen === b.length, we don't need to check b[i] here if (a[i] < b[i]) { return -1; } @@ -40,6 +77,8 @@ export const sortDomains = (inputs: string[], gorhill: PublicSuffixList) => { return acc; }, new Map()); + const cache = new TwoKeyCache(); + const sorter = (a: string, b: string) => { if (a === b) return 0; @@ -48,10 +87,12 @@ export const sortDomains = (inputs: string[], gorhill: PublicSuffixList) => { // avoid compare same thing twice if (a === $a && b === $b) { - return compare(a, b); + return cache.apply(a, b, compare); } - return compare($a, $b) || compare(a, b); + return cache.apply($a, $b, compare) || cache.apply(a, b, compare); }; - return inputs.sort(sorter); + const r = inputs.sort(sorter); + console.log('hit count', cache.hitCount); + return r; };