@ benchsdk/ 客户端
背相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相.
@benchsdk/client全部再出口@benchsdk/runner表面和保存遗产createBenchmarkClient().runWorker(options)拼写。 新项目应从@benchsdk/runner作者/操作助手或@benchsdk/api用于原始REST类型.
计算SDK基准管弦乐器的客户和工人助手.
此套件与平台拥有的基准/运行/参与者/工人API进行会谈. 它没有薄荷罐头跑步、工人、尝试、事件或任务标识。 工人要求平台分配的工作,在指定范围内执行任务指数,并发送 task_results 分批返回平台.
安装
npm install @benchsdk/client
高级基准作者
defineBenchmarkConfig编号 :defineTask财务报告和审定财务报表 本地管弦乐手)@benchsdk/runner此包是 REST 传输 + 只有工人发动机.
认证
createBenchmarkClient 需要平台 API 键或 OAuth 令牌。 提供
apiKey编号 :token 直接或设置 BENCHMARKS_PLATFORM_API_KEY 或者说
BENCHMARKS_PLATFORM_TOKEN 在环境中.
运行一个工作者
import { createBenchmarkClient } from '@benchsdk/client';
import { compute } from 'computesdk';
const client = createBenchmarkClient({
apiKey: process.env.BENCHMARKS_PLATFORM_API_KEY,
});
// `task` is a raw function; declare named steps imperatively via `step(...)`,
// so values flow between steps with closures and cleanup runs in a `finally`.
const { assignment, records } = await client.runWorker({
benchmarkSlug: 'scale',
runId: process.env.BENCHMARK_RUN_ID!,
participantSlug: 'e2b',
processKind: 'container',
processKey: process.env.HOSTNAME,
concurrency: 100,
task: async ({ assignment, step }) => {
const sandbox = await step('create', () =>
compute.sandbox.create({ provider: assignment.provider ?? 'e2b' }),
);
try {
await step('readiness', () => sandbox.runCommand('true'), { readiness: 'internal' });
await step('exec.first-command', () => sandbox.runCommand('node -v'));
// A `readiness: 'poll'` step reports active concurrency and waits until
// the platform reports the participant's step is ready (a barrier).
await step('pause', () => {}, { readiness: 'poll' });
return { sandboxId: sandbox.id };
} finally {
await step('destroy', () => sandbox.destroy());
}
},
});
client.runWorker(...) 对参与者的下一个待定平台任务提出索赔。 如果没有工作,它会返回 { assignment: null, records: [] }。 。 。 .
任务结果被分批冲入平台,默认为1000个记录. 设定 batchSize sDK验证每批5000个记录的平台限制。 工人还默认每隔30秒冲出部分批次 flushIntervalMs,在最后完成或关闭时总是冲出待决记录.
创建平台运行
import { createBenchmarkClient } from '@benchsdk/client';
const client = createBenchmarkClient({
apiKey: process.env.BENCHMARKS_PLATFORM_API_KEY,
});
await client.upsertBenchmark('scale', {
name: 'Scale',
config: { timeoutMs: 120_000 },
});
const { run } = await client.createRun('scale', {
name: '10k smoke',
totalTasks: 10_000,
workerCount: 20,
participants: ['e2b', 'modal'],
config: { timeoutMs: 120_000 },
});
await client.planWorkers('scale', run.id, 'e2b');
await client.planWorkers('scale', run.id, 'modal');
console.log(run.id);
工人必须事先计划好 client.runWorker(...) 可要求指派任务.
API 密码
工人发动机
client.runWorker(options)
这个 task 函数接收 :
| 外地 | 类型 | 说明 |
|---|---|---|
assignment | BenchmarkAssignment | 该工人的平台拥有的任务 |
taskIndex | number | 基准运行范围内的决定因素任务索引 |
step | (name, fn, options?) => Promise<R> | 运行 fn 并记录其时间/结果 |
如果任务返回 JSON 对象, 它将作为任务结果存储 data。 。 。 .
step(name, fn, options) 支持通过 options数字 :
| 选项 | 类型 | 说明 |
|---|---|---|
reportConcurrency | boolean? | 在工人心跳中包含此步骤的主动数 。 默认为 true |
concurrency | number? | 这个步骤的每个工人目标. 工人货币/分配指标的默认值 |
readiness | 'poll' | 'internal'? | 准备状态协调模式。 默认为 'internal'启用 'poll' 用于平台协调障碍步骤 |
readyPollIntervalMs | number? | 等待时的投票间隔 。 默认为 1000 |
readyTimeoutMs | number? | 最大待机时间 |
低级客户端
client.updateBenchmark(benchmarkSlug, input)
client.updateRun(benchmarkSlug, runId, input)
client.updateParticipant(benchmarkSlug, runId, participantSlug, input)
client.planWorkers(benchmarkSlug, runId, participantSlug)
client.getWorker(benchmarkSlug, runId, workerId)
client.updateWorker(benchmarkSlug, runId, workerId, input)
client.claimWorker(benchmarkSlug, runId, participantSlug, { processKind, processKey })
client.sendTaskResults({ benchmarkSlug, runId, workerId, attemptId, sequenceNumber, isFinal, records })
client.uploadWorkerArtifact(benchmarkSlug, runId, workerId, {
attemptId,
kind: 'log',
name: 'coordinator.log',
contentType: 'text/plain; charset=utf-8',
body: logText,
})
client.heartbeatWorker(benchmarkSlug, runId, workerId, {
attemptId,
currentStep: 'pause',
concurrency: [{ step: 'pause', active: 100, target: 100 }],
})
client.getRunProgress(benchmarkSlug, runId)
client.getBenchmarkResults(benchmarkSlug, { limit })
client.getRunResults(benchmarkSlug, runId)
client.getRunTaskResults(benchmarkSlug, runId, { bucketSize, failureLimit })
client.getRunTimeline(benchmarkSlug, runId, { bucketMs })
client.getRunImports(benchmarkSlug, runId)
client.completeWorker(benchmarkSlug, runId, workerId, attemptId)
client.failWorker(benchmarkSlug, runId, workerId, attemptId, error)
client.runWorker(options)
不适合的习惯协调员 runWorker,使用最佳记者包装:
const reporter = await BenchmarkReporter.claim({
benchmarkSlug: 'scale',
runId,
participantSlug: 'e2b',
processKind: 'container',
processKey: instanceId,
});
reporter?.setProgress({ done, inFlight, errors });
reporter?.recordResult(record);
await reporter?.waitForStepReady({ step: 'ready.barrier', timeoutMs: 15 * 60_000 });
await reporter?.uploadArtifact({
kind: 'log',
name: 'coordinator.log',
contentType: 'text/plain; charset=utf-8',
body: logText,
});
await reporter?.finish(false);
BenchmarkReporter 吞入平台遥测故障,用于索赔,心跳,结果冲洗,文物上传,并完成通话. 即使暂时没有报告,基准工作也可以继续进行.
对于 runWorker,使用时 onFinish 在最后任务结果被冲出之后,并在工人尝试完成或失败之前,上传一次工人级日志:
client.runWorker({
benchmarkSlug: 'scale',
runId,
participantSlug: 'e2b',
task,
onFinish: async ({ uploadArtifact }) => {
await uploadArtifact({
kind: 'log',
name: 'coordinator.log',
contentType: 'text/plain; charset=utf-8',
body: logText,
});
},
});
对于协调卫生文物,抽样系统衡量标准:
const metrics = createSystemMetricsCollector();
const samples = [await metrics.sample()];
metrics.stop();
client.getRunProgress(...) 返回运行摘要加每个参与者的工人、任务和货币进度 :
const progress = await client.getRunProgress('scale', runId);
console.log(progress.summary.status);
console.log(progress.summary.participants);
const participant = progress.participants.find((item) => item.slug === 'e2b');
console.log(participant?.status);
console.log(participant?.workers);
console.log(participant?.tasks.completionRatio);
console.log(participant?.concurrency.find((item) => item.step === 'pause')?.ready);
大多数工人应该使用 client.runWorker(...)。 。 。 .
任务结果形状
{
"taskIndex": 0,
"status": "success",
"startedAt": "2026-06-03T00:00:00.000Z",
"completedAt": "2026-06-03T00:00:01.000Z",
"latencyMs": 1000,
"steps": [
{ "name": "create", "status": "success", "startedAt": "...", "completedAt": "...", "latencyMs": 700 },
{ "name": "exec.first-command", "status": "success", "startedAt": "...", "completedAt": "...", "latencyMs": 120 },
{ "name": "destroy", "status": "success", "startedAt": "...", "completedAt": "...", "latencyMs": 180 }
],
"data": {
"sandboxId": "..."
}
}