Skip to content
My custom sidebar

parallelFilter

typescript
import { parallelFilter } from "perry/thread";

function parallelFilter<T>(data: T[], predicate: (item: T) => boolean): T[];

该方法可跨所有可用的 CPU 核心并行过滤数组。返回一个新数组,仅包含断言函数返回真值的元素,且元素顺序保持不变。

基本用法

typescript
import { parallelFilter } from "perry/thread";

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const evens = parallelFilter(numbers, (x) => x % 2 === 0);
// [2, 4, 6, 8, 10]

工作原理

输入: [a, b, c, d, e, f, g, h]     (8 个元素,4 个 CPU 核心)

  核心 1: [a, b] → 校验 → [a]       (b 被过滤掉)
  核心 2: [c, d] → 校验 → [c, d]    (两者均保留)
  核心 3: [e, f] → 校验 → []        (两者均被过滤掉)
  核心 4: [g, h] → 校验 → [h]       (g 被过滤掉)

输出: [a, c, d, h]                 (按原始顺序拼接结果)

每个核心独立校验其分配到的元素分片。所有线程执行完成后,结果会按元素原始顺序合并。

为何不直接使用 .filter()

常规的 .filter() 方法运行在单个线程上。对于包含大量元素且断言函数计算成本较高的数组,parallelFilter 可将计算任务分发至多个核心:

typescript
// 单线程 — 仅单个核心执行所有任务
const results = data.filter((item) => expensivePredicate(item));

// 并行处理 — 所有核心分摊任务
import { parallelFilter } from "perry/thread";
const results = parallelFilter(data, (item) => expensivePredicate(item));

注意权衡:parallelFilter 存在线程间值拷贝的性能开销。仅当断言函数的计算成本足以抵消该开销时,才建议使用此方法。

变量捕获

parallelMap 类似,断言函数可捕获外部变量。被捕获的变量会被深度拷贝至每个线程:

typescript
import { parallelFilter } from "perry/thread";

const minScore = 85;
const maxAge = 30;

// minScore 和 maxAge 被捕获并拷贝至每个线程
const qualified = parallelFilter(candidates, (c) => {
    return c.score >= minScore && c.age <= maxAge;
});

不可捕获可变变量——编译器会在编译阶段拒绝此类操作。

示例

过滤大型数据集

typescript
import { parallelFilter } from "perry/thread";

const transactions = getTransactionLog(); // 数百万条记录

const suspicious = parallelFilter(transactions, (tx) => {
    return tx.amount > 10000
        && tx.country !== tx.user.homeCountry
        && tx.timestamp.hour < 6;
});

与 parallelMap 结合使用

typescript
import { parallelMap, parallelFilter } from "perry/thread";

// 步骤 1:并行过滤出相关元素
const active = parallelFilter(users, (u) => u.isActive && u.age >= 18);

// 步骤 2:并行转换过滤后的结果
const profiles = parallelMap(active, (u) => ({
    name: u.name,
    score: computeScore(u),
}));

包含重度计算的断言函数

typescript
import { parallelFilter } from "perry/thread";

// 每次断言调用涉及大量计算 — 非常适合并行化处理
const valid = parallelFilter(certificates, (cert) => {
    return verifyCertificateChain(cert) && !isRevoked(cert);
});

性能说明

建议在以下场景使用 parallelFilter

  • 数组包含大量元素(数百个及以上)
  • 断言函数每个元素的计算量较大
  • 需要在过滤过程中保持用户界面响应性

对于小型数组的简单断言场景,常规 .filter() 方法速度更快(无线程调度开销)。

MIT License.