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++) {
|
||||
const originalIndex = unpackFirst(dumped[i][1]);
|
||||
const flag = unpackSecond(dumped[i][1]);
|
||||
const originalIndex = unpackFirst(dumped[i]);
|
||||
const flag = unpackSecond(dumped[i]);
|
||||
|
||||
const type = flag === flagDomain ? 'DOMAIN' : 'DOMAIN-SUFFIX';
|
||||
|
||||
|
||||
@ -63,7 +63,7 @@ const walkHostnameTokens = (hostname: string, onToken: (token: string) => boolea
|
||||
const l = tokens.length - 1;
|
||||
for (let i = l; i >= 0; i--) {
|
||||
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
|
||||
&& 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.
|
||||
*/
|
||||
const find = (inputSuffix: string, /** @default true */ includeEqualWithSuffix = true): string[] => {
|
||||
const find = (
|
||||
inputSuffix: string,
|
||||
/** @default true */ includeEqualWithSuffix = true
|
||||
): string[] => {
|
||||
if (smolTree) {
|
||||
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 onMatches = includeEqualWithSuffix
|
||||
// fast path (default option)
|
||||
? (suffix: string[]) => matches.push(suffix)
|
||||
// slow path
|
||||
: (suffix: string[]) => {
|
||||
if (suffix.some((t, i) => t !== inputTokens[i])) {
|
||||
if (!deepEqualArray(suffix, inputTokens)) {
|
||||
matches.push(suffix);
|
||||
}
|
||||
};
|
||||
@ -332,28 +337,6 @@ export const createTrie = <Meta = any>(from?: string[] | Set<string> | null, smo
|
||||
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.
|
||||
*/
|
||||
@ -396,6 +379,16 @@ export const createTrie = <Meta = any>(from?: string[] | Set<string> | null, smo
|
||||
return results;
|
||||
};
|
||||
|
||||
const dumpMeta = () => {
|
||||
const results: Meta[] = [];
|
||||
|
||||
walk((suffix, meta) => {
|
||||
results.push(meta);
|
||||
});
|
||||
|
||||
return results;
|
||||
};
|
||||
|
||||
const dumpWithMeta = () => {
|
||||
const results: Array<[string, Meta]> = [];
|
||||
|
||||
@ -463,11 +456,11 @@ export const createTrie = <Meta = any>(from?: string[] | Set<string> | null, smo
|
||||
add,
|
||||
contains,
|
||||
find,
|
||||
substractSetInPlaceFromFound,
|
||||
remove,
|
||||
delete: remove,
|
||||
has,
|
||||
dump,
|
||||
dumpMeta,
|
||||
dumpWithMeta,
|
||||
get size() {
|
||||
if (smolTree) {
|
||||
@ -486,3 +479,12 @@ export const createTrie = <Meta = any>(from?: string[] | Set<string> | null, smo
|
||||
};
|
||||
|
||||
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