mirror of
https://github.com/SukkaW/Surge.git
synced 2025-12-12 01:00:34 +08:00
Perf: optimize sort domains & preload promise
This commit is contained in:
parent
eaf993deca
commit
6daf8e3bb4
@ -13,6 +13,9 @@ import picocolors from 'picocolors';
|
|||||||
import { fetchRemoteTextByLine } from './lib/fetch-text-by-line';
|
import { fetchRemoteTextByLine } from './lib/fetch-text-by-line';
|
||||||
import { processLine } from './lib/process-line';
|
import { processLine } from './lib/process-line';
|
||||||
import { TTL, deserializeArray, fsCache, serializeArray } from './lib/cache-filesystem';
|
import { TTL, deserializeArray, fsCache, serializeArray } from './lib/cache-filesystem';
|
||||||
|
import { createMemoizedPromise } from './lib/memo-promise';
|
||||||
|
|
||||||
|
import * as SetHelpers from 'mnemonist/set';
|
||||||
|
|
||||||
const s = new Sema(2);
|
const s = new Sema(2);
|
||||||
|
|
||||||
@ -80,15 +83,26 @@ const querySpeedtestApi = async (keyword: string): Promise<Array<string | null>>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getPreviousSpeedtestDomainsPromise = createMemoizedPromise(async () => {
|
||||||
|
const domains = new Set<string>();
|
||||||
|
for await (const l of await fetchRemoteTextByLine('https://ruleset.skk.moe/List/domainset/speedtest.conf')) {
|
||||||
|
const line = processLine(l);
|
||||||
|
if (line) {
|
||||||
|
domains.add(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return domains;
|
||||||
|
});
|
||||||
|
|
||||||
export const buildSpeedtestDomainSet = task(import.meta.path, async (span) => {
|
export const buildSpeedtestDomainSet = task(import.meta.path, async (span) => {
|
||||||
// Predefined domainset
|
// Predefined domainset
|
||||||
/** @type {Set<string>} */
|
/** @type {Set<string>} */
|
||||||
const domains = new Set<string>([
|
const domains = new Set<string>([
|
||||||
|
// speedtest.net
|
||||||
'.speedtest.net',
|
'.speedtest.net',
|
||||||
'.speedtestcustom.com',
|
'.speedtestcustom.com',
|
||||||
'.ooklaserver.net',
|
'.ooklaserver.net',
|
||||||
'.speed.misaka.one',
|
'.speed.misaka.one',
|
||||||
'.speed.cloudflare.com',
|
|
||||||
'.speedtest.rt.ru',
|
'.speedtest.rt.ru',
|
||||||
'.speedtest.aptg.com.tw',
|
'.speedtest.aptg.com.tw',
|
||||||
'.speedtest.gslnetworks.com',
|
'.speedtest.gslnetworks.com',
|
||||||
@ -133,6 +147,13 @@ export const buildSpeedtestDomainSet = task(import.meta.path, async (span) => {
|
|||||||
'.speedtest.optitel.com.au',
|
'.speedtest.optitel.com.au',
|
||||||
'.speednet.net.tr',
|
'.speednet.net.tr',
|
||||||
'.speedtest.angolacables.co.ao',
|
'.speedtest.angolacables.co.ao',
|
||||||
|
'.ookla-speedtest.fsr.com',
|
||||||
|
'.speedtest.comnet.com.tr',
|
||||||
|
'.speedtest.gslnetworks.com.au',
|
||||||
|
'.speedtest.gslnetworks.com',
|
||||||
|
'.speedtestunonet.com.br',
|
||||||
|
// Cloudflare
|
||||||
|
'.speed.cloudflare.com',
|
||||||
// Wi-Fi Man
|
// Wi-Fi Man
|
||||||
'.wifiman.com',
|
'.wifiman.com',
|
||||||
'.wifiman.me',
|
'.wifiman.me',
|
||||||
@ -152,12 +173,7 @@ export const buildSpeedtestDomainSet = task(import.meta.path, async (span) => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
await span.traceChild('fetch previous speedtest domainset').traceAsyncFn(async () => {
|
await span.traceChild('fetch previous speedtest domainset').traceAsyncFn(async () => {
|
||||||
for await (const l of await fetchRemoteTextByLine('https://ruleset.skk.moe/List/domainset/speedtest.conf')) {
|
SetHelpers.add(domains, await getPreviousSpeedtestDomainsPromise());
|
||||||
const line = processLine(l);
|
|
||||||
if (line) {
|
|
||||||
domains.add(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await new Promise<void>((resolve) => {
|
await new Promise<void>((resolve) => {
|
||||||
|
|||||||
@ -9,8 +9,7 @@ import { ALL, NORTH_AMERICA, EU, HK, TW, JP, KR } from '../Source/stream';
|
|||||||
import { SHARED_DESCRIPTION } from './lib/constants';
|
import { SHARED_DESCRIPTION } from './lib/constants';
|
||||||
|
|
||||||
export const createRulesetForStreamService = (span: Span, fileId: string, title: string, streamServices: Array<import('../Source/stream').StreamService>) => {
|
export const createRulesetForStreamService = (span: Span, fileId: string, title: string, streamServices: Array<import('../Source/stream').StreamService>) => {
|
||||||
const childSpan = span.traceChild(fileId);
|
return span.traceChild(fileId).traceAsyncFn(async (childSpan) => Promise.all([
|
||||||
return [
|
|
||||||
// Domains
|
// Domains
|
||||||
createRuleset(
|
createRuleset(
|
||||||
childSpan,
|
childSpan,
|
||||||
@ -48,20 +47,20 @@ export const createRulesetForStreamService = (span: Span, fileId: string, title:
|
|||||||
path.resolve(import.meta.dir, `../List/ip/${fileId}.conf`),
|
path.resolve(import.meta.dir, `../List/ip/${fileId}.conf`),
|
||||||
path.resolve(import.meta.dir, `../Clash/ip/${fileId}.txt`)
|
path.resolve(import.meta.dir, `../Clash/ip/${fileId}.txt`)
|
||||||
)
|
)
|
||||||
];
|
]));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const buildStreamService = task(import.meta.path, async (span) => {
|
export const buildStreamService = task(import.meta.path, async (span) => {
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
...createRulesetForStreamService(span, 'stream', 'All', ALL),
|
createRulesetForStreamService(span, 'stream', 'All', ALL),
|
||||||
...createRulesetForStreamService(span, 'stream_us', 'North America', NORTH_AMERICA),
|
createRulesetForStreamService(span, 'stream_us', 'North America', NORTH_AMERICA),
|
||||||
...createRulesetForStreamService(span, 'stream_eu', 'Europe', EU),
|
createRulesetForStreamService(span, 'stream_eu', 'Europe', EU),
|
||||||
...createRulesetForStreamService(span, 'stream_hk', 'Hong Kong', HK),
|
createRulesetForStreamService(span, 'stream_hk', 'Hong Kong', HK),
|
||||||
...createRulesetForStreamService(span, 'stream_tw', 'Taiwan', TW),
|
createRulesetForStreamService(span, 'stream_tw', 'Taiwan', TW),
|
||||||
...createRulesetForStreamService(span, 'stream_jp', 'Japan', JP),
|
createRulesetForStreamService(span, 'stream_jp', 'Japan', JP),
|
||||||
// ...createRulesetForStreamService('stream_au', 'Oceania', AU),
|
// createRulesetForStreamService('stream_au', 'Oceania', AU),
|
||||||
...createRulesetForStreamService(span, 'stream_kr', 'Korean', KR)
|
createRulesetForStreamService(span, 'stream_kr', 'Korean', KR)
|
||||||
// ...createRulesetForStreamService('stream_south_east_asia', 'South East Asia', SOUTH_EAST_ASIA)
|
// createRulesetForStreamService('stream_south_east_asia', 'South East Asia', SOUTH_EAST_ASIA)
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -16,8 +16,9 @@ export const parseWithoutDetectIp = parse2;
|
|||||||
|
|
||||||
let gothillGetDomainCache: ReturnType<typeof createCache> | null = null;
|
let gothillGetDomainCache: ReturnType<typeof createCache> | null = null;
|
||||||
export const createCachedGorhillGetDomain = (gorhill: PublicSuffixList) => {
|
export const createCachedGorhillGetDomain = (gorhill: PublicSuffixList) => {
|
||||||
|
gothillGetDomainCache ??= createCache('cached-gorhill-get-domain', true);
|
||||||
return (domain: string) => {
|
return (domain: string) => {
|
||||||
gothillGetDomainCache ??= createCache('cached-gorhill-get-domain', true);
|
// we do know gothillGetDomainCache exists here
|
||||||
return gothillGetDomainCache.sync(domain, () => gorhill.getDomain(domain[0] === '.' ? domain.slice(1) : domain));
|
return gothillGetDomainCache!.sync(domain, () => gorhill.getDomain(domain[0] === '.' ? domain.slice(1) : domain));
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,7 +1,12 @@
|
|||||||
export const createMemoizedPromise = <T>(fn: () => Promise<T>): () => Promise<T> => {
|
export const createMemoizedPromise = <T>(fn: () => Promise<T>, preload = true): () => Promise<T> => {
|
||||||
let promise: Promise<T> | null = null;
|
let promise: Promise<T> | null = null;
|
||||||
|
|
||||||
|
if (preload) {
|
||||||
|
promise = fn();
|
||||||
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
promise ||= fn();
|
promise ??= fn();
|
||||||
return promise;
|
return promise;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -35,18 +35,14 @@ const compare = (a: string | null, b: string | null) => {
|
|||||||
|
|
||||||
export const sortDomains = (inputs: string[], gorhill: PublicSuffixList) => {
|
export const sortDomains = (inputs: string[], gorhill: PublicSuffixList) => {
|
||||||
const getDomain = createCachedGorhillGetDomain(gorhill);
|
const getDomain = createCachedGorhillGetDomain(gorhill);
|
||||||
const domains = inputs.reduce<Record<string, string>>((acc, cur) => {
|
const domains = inputs.reduce<Map<string, string>>((acc, cur) => {
|
||||||
acc[cur] ||= getDomain(cur);
|
if (!acc.has(cur)) acc.set(cur, getDomain(cur));
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, new Map());
|
||||||
|
|
||||||
const sorter = (a: string, b: string) => {
|
const sorter = (a: string, b: string) => {
|
||||||
if (a === b) return 0;
|
if (a === b) return 0;
|
||||||
|
return compare(domains.get(a)!, domains.get(b)!) || compare(a, b);
|
||||||
const aDomain = domains[a];
|
|
||||||
const bDomain = domains[b];
|
|
||||||
|
|
||||||
return compare(aDomain, bDomain) || compare(a, b);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return inputs.sort(sorter);
|
return inputs.sort(sorter);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user