mirror of
https://github.com/SukkaW/Surge.git
synced 2025-12-14 18:20:35 +08:00
Perf: a few improvements to trie
This commit is contained in:
parent
a004ffb960
commit
3bd0ebe36e
@ -160,11 +160,11 @@ const processRuleSet = (ruleSet: string[]) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const dumped = trie.dumpWithMeta();
|
const dumped = trie.dumpMeta();
|
||||||
|
|
||||||
for (let i = 0, len = dumped.length; i < len; i++) {
|
for (let i = 0, len = dumped.length; i < len; i++) {
|
||||||
const originalIndex = unpackFirst(dumped[i][1]);
|
const originalIndex = unpackFirst(dumped[i]);
|
||||||
const flag = unpackSecond(dumped[i][1]);
|
const flag = unpackSecond(dumped[i]);
|
||||||
|
|
||||||
const type = flag === flagDomain ? 'DOMAIN' : 'DOMAIN-SUFFIX';
|
const type = flag === flagDomain ? 'DOMAIN' : 'DOMAIN-SUFFIX';
|
||||||
|
|
||||||
|
|||||||
@ -63,7 +63,7 @@ const walkHostnameTokens = (hostname: string, onToken: (token: string) => boolea
|
|||||||
const l = tokens.length - 1;
|
const l = tokens.length - 1;
|
||||||
for (let i = l; i >= 0; i--) {
|
for (let i = l; i >= 0; i--) {
|
||||||
if (
|
if (
|
||||||
i < l
|
i < l // when i === l, we are at the first of hostname, no splitor there
|
||||||
// when onToken returns true, we should skip the rest of the loop
|
// when onToken returns true, we should skip the rest of the loop
|
||||||
&& onToken('.')
|
&& onToken('.')
|
||||||
) {
|
) {
|
||||||
@ -304,7 +304,10 @@ export const createTrie = <Meta = any>(from?: string[] | Set<string> | null, smo
|
|||||||
/**
|
/**
|
||||||
* Method used to retrieve every item in the trie with the given prefix.
|
* Method used to retrieve every item in the trie with the given prefix.
|
||||||
*/
|
*/
|
||||||
const find = (inputSuffix: string, /** @default true */ includeEqualWithSuffix = true): string[] => {
|
const find = (
|
||||||
|
inputSuffix: string,
|
||||||
|
/** @default true */ includeEqualWithSuffix = true
|
||||||
|
): string[] => {
|
||||||
if (smolTree) {
|
if (smolTree) {
|
||||||
throw new Error('A Trie with smolTree enabled cannot perform find!');
|
throw new Error('A Trie with smolTree enabled cannot perform find!');
|
||||||
}
|
}
|
||||||
@ -316,9 +319,11 @@ export const createTrie = <Meta = any>(from?: string[] | Set<string> | null, smo
|
|||||||
const matches: string[][] = [];
|
const matches: string[][] = [];
|
||||||
|
|
||||||
const onMatches = includeEqualWithSuffix
|
const onMatches = includeEqualWithSuffix
|
||||||
|
// fast path (default option)
|
||||||
? (suffix: string[]) => matches.push(suffix)
|
? (suffix: string[]) => matches.push(suffix)
|
||||||
|
// slow path
|
||||||
: (suffix: string[]) => {
|
: (suffix: string[]) => {
|
||||||
if (suffix.some((t, i) => t !== inputTokens[i])) {
|
if (!deepEqualArray(suffix, inputTokens)) {
|
||||||
matches.push(suffix);
|
matches.push(suffix);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -332,28 +337,6 @@ export const createTrie = <Meta = any>(from?: string[] | Set<string> | null, smo
|
|||||||
return matches.map((m) => fastStringArrayJoin(m, ''));
|
return matches.map((m) => fastStringArrayJoin(m, ''));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Works like trie.find, but instead of returning the matches as an array, it removes them from the given set in-place.
|
|
||||||
*/
|
|
||||||
const substractSetInPlaceFromFound = (inputSuffix: string, set: Set<string>) => {
|
|
||||||
if (smolTree) {
|
|
||||||
throw new Error('A Trie with smolTree enabled cannot perform substractSetInPlaceFromFound!');
|
|
||||||
}
|
|
||||||
|
|
||||||
const inputTokens = hostnameToTokens(inputSuffix);
|
|
||||||
|
|
||||||
const res = walkIntoLeafWithTokens(inputTokens);
|
|
||||||
if (res === null) return;
|
|
||||||
|
|
||||||
const onMatches = (suffix: string[]) => set.delete(fastStringArrayJoin(suffix, ''));
|
|
||||||
|
|
||||||
walk(
|
|
||||||
onMatches,
|
|
||||||
res.node, // Performing DFS from prefix
|
|
||||||
inputTokens
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method used to delete a prefix from the trie.
|
* Method used to delete a prefix from the trie.
|
||||||
*/
|
*/
|
||||||
@ -396,6 +379,16 @@ export const createTrie = <Meta = any>(from?: string[] | Set<string> | null, smo
|
|||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const dumpMeta = () => {
|
||||||
|
const results: Meta[] = [];
|
||||||
|
|
||||||
|
walk((suffix, meta) => {
|
||||||
|
results.push(meta);
|
||||||
|
});
|
||||||
|
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
const dumpWithMeta = () => {
|
const dumpWithMeta = () => {
|
||||||
const results: Array<[string, Meta]> = [];
|
const results: Array<[string, Meta]> = [];
|
||||||
|
|
||||||
@ -463,11 +456,11 @@ export const createTrie = <Meta = any>(from?: string[] | Set<string> | null, smo
|
|||||||
add,
|
add,
|
||||||
contains,
|
contains,
|
||||||
find,
|
find,
|
||||||
substractSetInPlaceFromFound,
|
|
||||||
remove,
|
remove,
|
||||||
delete: remove,
|
delete: remove,
|
||||||
has,
|
has,
|
||||||
dump,
|
dump,
|
||||||
|
dumpMeta,
|
||||||
dumpWithMeta,
|
dumpWithMeta,
|
||||||
get size() {
|
get size() {
|
||||||
if (smolTree) {
|
if (smolTree) {
|
||||||
@ -486,3 +479,12 @@ export const createTrie = <Meta = any>(from?: string[] | Set<string> | null, smo
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type Trie = ReturnType<typeof createTrie>;
|
export type Trie = ReturnType<typeof createTrie>;
|
||||||
|
|
||||||
|
function deepEqualArray(a: string[], b: string[]) {
|
||||||
|
let len = a.length;
|
||||||
|
if (len !== b.length) return false;
|
||||||
|
while (len--) {
|
||||||
|
if (a[len] !== b[len]) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user