浏览代码

Perf: repalce `String#localeCompare` w/ simple ASCII-only compare

SukkaW 1 年之前
父节点
当前提交
c6f3a67711
共有 5 个文件被更改,包括 28 次插入6 次删除
  1. 2 2
      Build/build-public.ts
  2. 20 0
      Build/lib/misc.ts
  3. 2 1
      Build/lib/rules/domainset.ts
  4. 2 1
      Build/lib/stable-sort-domain.ts
  5. 2 2
      Build/lib/trie.ts

+ 2 - 2
Build/build-public.ts

@@ -7,7 +7,7 @@ import { treeDir } from './lib/tree-dir';
 import type { TreeType, TreeTypeArray } from './lib/tree-dir';
 
 import { OUTPUT_MOCK_DIR, OUTPUT_MODULES_DIR, PUBLIC_DIR, ROOT_DIR } from './constants/dir';
-import { mkdirp, writeFile } from './lib/misc';
+import { fastStringCompare, mkdirp, writeFile } from './lib/misc';
 import picocolors from 'picocolors';
 import { compareAndWriteFile } from './lib/create-file';
 
@@ -90,7 +90,7 @@ const priorityOrder: Record<'default' | string & {}, number> = {
   LICENSE: 70,
   default: Number.MAX_VALUE
 };
-const prioritySorter = (a: TreeType, b: TreeType) => ((priorityOrder[a.name] || priorityOrder.default) - (priorityOrder[b.name] || priorityOrder.default)) || a.name.localeCompare(b.name);
+const prioritySorter = (a: TreeType, b: TreeType) => ((priorityOrder[a.name] || priorityOrder.default) - (priorityOrder[b.name] || priorityOrder.default)) || fastStringCompare(a.name, b.name);
 
 const html = (string: TemplateStringsArray, ...values: any[]) => string.reduce((acc, str, i) => acc + str + (values[i] ?? ''), '');
 

+ 20 - 0
Build/lib/misc.ts

@@ -21,6 +21,26 @@ export function fastStringArrayJoin(arr: string[], sep: string) {
   return result;
 }
 
+export function fastStringCompare(a: string, b: string) {
+  const lenA = a.length;
+  const lenB = b.length;
+  const minLen = lenA < lenB ? lenA : lenB;
+
+  for (let i = 0; i < minLen; ++i) {
+    const ca = a.charCodeAt(i);
+    const cb = b.charCodeAt(i);
+
+    if (ca > cb) return 1;
+    if (ca < cb) return -1;
+  }
+
+  if (lenA === lenB) {
+    return 0;
+  }
+
+  return lenA > lenB ? 1 : -1;
+};
+
 interface Write {
   (
     destination: string,

+ 2 - 1
Build/lib/rules/domainset.ts

@@ -5,6 +5,7 @@ import type { SingboxSourceFormat } from '../singbox';
 
 import * as tldts from 'tldts-experimental';
 import { looseTldtsOpt } from '../../constants/loose-tldts-opt';
+import { fastStringCompare } from '../misc';
 
 type Preprocessed = string[];
 
@@ -89,7 +90,7 @@ export class DomainsetOutput extends RuleOutput<Preprocessed> {
       )
       .entries())
       .filter(a => a[1] > 9)
-      .sort((a, b) => (b[1] - a[1]) || a[0].localeCompare(b[0]))
+      .sort((a, b) => (b[1] - a[1]) || fastStringCompare(a[0], b[0]))
       .map(([domain, count]) => `${domain}${' '.repeat(100 - domain.length)}${count}`);
   }
 

+ 2 - 1
Build/lib/stable-sort-domain.ts

@@ -3,10 +3,11 @@
 // enough when sorting.
 import * as tldts from 'tldts-experimental';
 import { looseTldtsOpt } from '../constants/loose-tldts-opt';
+import { fastStringCompare } from './misc';
 
 export function compare(a: string, b: string) {
   if (a === b) return 0;
-  return (a.length - b.length) || a.localeCompare(b);
+  return (a.length - b.length) || fastStringCompare(a, b);
 }
 
 export function buildParseDomainMap(inputs: string[]) {

+ 2 - 2
Build/lib/trie.ts

@@ -2,7 +2,7 @@
  * Hostbane-Optimized Trie based on Mnemonist Trie
  */
 
-import { fastStringArrayJoin } from './misc';
+import { fastStringArrayJoin, fastStringCompare } from './misc';
 import util from 'node:util';
 import { noop } from 'foxact/noop';
 import FIFO from './fifo';
@@ -251,7 +251,7 @@ abstract class Triebase<Meta = any> {
 
   static compare(this: void, a: string, b: string) {
     if (a === b) return 0;
-    return (a.length - b.length) || a.localeCompare(b);
+    return (a.length - b.length) || fastStringCompare(a, b);
   }
 
   private walkWithSort(