name: midnight-proofs:prover-optimization
description: 用于优化证明器性能、减少证明生成内存占用、在Docker或Kubernetes中配置证明器基础设施、实现并行证明生成或诊断证明器瓶颈。
证明器优化
通过内存优化、并行化和基础设施配置,为生产工作负载调优ZK证明器性能。
何时使用
- 为高吞吐量服务优化证明生成速度
- 减少证明生成期间的内存占用
- 配置证明器基础设施(Docker、Kubernetes)
- 使用工作池实现并行证明生成
- 诊断和修复证明器性能瓶颈
关键概念
性能因素
| 因素 |
影响 |
优化方法 |
| 电路复杂度 |
高 |
尽可能简化电路 |
| 内存分配 |
高 |
调优JVM/Node内存设置 |
| CPU核心数 |
中 |
根据可用核心数扩展工作线程 |
| 磁盘I/O |
低 |
对电路密钥使用SSD |
| 网络 |
低 |
与依赖服务同地部署 |
内存需求
证明生成是内存密集型操作。典型需求:
| 电路复杂度 |
内存(每证明) |
| 简单(< 1000约束) |
512MB - 1GB |
| 中等(1000-10000约束) |
1GB - 4GB |
| 复杂(> 10000约束) |
4GB - 16GB |
吞吐量估算
证明数/小时 = (核心数 / 每核心证明数) * 3600 / 平均证明时间秒数
示例:8核心,每核心2个证明,15秒证明时间:
(8 / 2) * 3600 / 15 = 960 证明/小时
参考资料
示例
快速开始
1. 基础内存配置
import { createProver } from '@midnight-ntwrk/midnight-js-prover';
const prover = await createProver({
circuitKeysPath: './circuit-keys',
memoryLimit: 8192, // 8GB
threads: 4, // 工作线程数
});
2. 环境变量
# Node.js内存设置
export NODE_OPTIONS="--max-old-space-size=8192"
# 证明器特定设置
export PROVER_MEMORY_LIMIT=8192
export PROVER_THREADS=4
export PROVER_PRELOAD_CIRCUITS="transfer,mint,burn"
3. Docker资源限制
# docker-compose.yml
services:
prover:
image: prover-service:latest
deploy:
resources:
limits:
cpus: '4'
memory: 8G
reservations:
cpus: '2'
memory: 4G
常用模式
电路密钥预加载
// 在启动时预加载以避免加载延迟
const prover = await createProver({
circuitKeysPath: './circuit-keys',
preloadCircuits: ['transfer', 'mint', 'burn'],
});
// 验证电路已加载
const status = await prover.getStatus();
console.log('已加载电路:', status.loadedCircuits);
内存监控
import v8 from 'v8';
function getMemoryUsage(): {
heapUsed: number;
heapTotal: number;
external: number;
} {
const stats = v8.getHeapStatistics();
return {
heapUsed: Math.round(stats.used_heap_size / 1024 / 1024),
heapTotal: Math.round(stats.total_heap_size / 1024 / 1024),
external: Math.round(stats.external_memory / 1024 / 1024),
};
}
// 在证明生成前后记录内存使用情况
console.log('之前:', getMemoryUsage());
await prover.prove(circuitId, witness);
console.log('之后:', getMemoryUsage());
背压控制
class BackpressureController {
private activeProofs = 0;
private maxConcurrent: number;
private waitQueue: Array<() => void> = [];
constructor(maxConcurrent: number) {
this.maxConcurrent = maxConcurrent;
}
async acquire(): Promise<void> {
if (this.activeProofs < this.maxConcurrent) {
this.activeProofs++;
return;
}
// 等待可用槽位
await new Promise<void>((resolve) => {
this.waitQueue.push(resolve);
});
this.activeProofs++;
}
release(): void {
this.activeProofs--;
const next = this.waitQueue.shift();
if (next) next();
}
async withBackpressure<T>(fn: () => Promise<T>): Promise<T> {
await this.acquire();
try {
return await fn();
} finally {
this.release();
}
}
}
// 使用示例
const controller = new BackpressureController(4); // 最多4个并发证明
await controller.withBackpressure(async () => {
return await prover.prove(circuitId, witness);
});
优雅降级
async function proveWithFallback(
circuitId: string,
witness: WitnessData
): Promise<Proof> {
const memoryUsage = getMemoryUsage();
// 如果内存使用率高,在开始新证明前等待
if (memoryUsage.heapUsed > 6000) {
console.warn('内存使用率高,等待中...');
await new Promise((r) => setTimeout(r, 5000));
// 如果可用,强制垃圾回收
if (global.gc) {
global.gc();
}
}
try {
return await prover.prove(circuitId, witness);
} catch (error) {
if (error.message.includes('out of memory')) {
// 降低并发度后重试
console.warn('内存不足错误,GC后重试...');
if (global.gc) global.gc();
await new Promise((r) => setTimeout(r, 2000));
return await prover.prove(circuitId, witness);
}
throw error;
}
}
性能指标
import { Counter, Histogram, Gauge } from 'prom-client';
const proofDuration = new Histogram({
name: 'proof_generation_duration_seconds',
help: '证明生成时长',
labelNames: ['circuit_id'],
buckets: [1, 5, 10, 15, 30, 60],
});
const proofCounter = new Counter({
name: 'proofs_generated_total',
help: '生成的证明总数',
labelNames: ['circuit_id', 'status'],
});
const memoryGauge = new Gauge({
name: 'prover_memory_usage_bytes',
help: '当前证明器内存使用量',
});
// 仪表化证明生成
async function proveWithMetrics(
circuitId: string,
witness: WitnessData
): Promise<Proof> {
const end = proofDuration.startTimer({ circuit_id: circuitId });
memoryGauge.set(process.memoryUsage().heapUsed);
try {
const proof = await prover.prove(circuitId, witness);
proofCounter.inc({ circuit_id: circuitId, status: 'success' });
return proof;
} catch (error) {
proofCounter.inc({ circuit_id: circuitId, status: 'error' });
throw error;
} finally {
end();
}
}
性能注意事项
| 关注点 |
缓解措施 |
| 内存碎片化 |
定期重启工作线程 |
| CPU限制 |
使用专用证明器节点 |
| GC暂停 |
调优GC设置,限制堆大小 |
| 电路加载时间 |
在启动时预加载电路 |
相关技能
proof-generation - 服务器端证明生成
proof-caching - 缓存证明以减少生成负载
proof-verification - 验证生成的证明
相关命令
当前未定义。