From b59952174bf8817194af1c09821da7296bcbc4b7 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 5 Apr 2026 15:50:56 +0000 Subject: [PATCH 1/2] perf(metrics): Increase output token counting chunk size from 100KB to 200KB Benchmarks show 200KB chunks are optimal for output token counting, reducing worker round-trips while maintaining good parallelism across available CPU cores. For a 3.9MB output (typical large repo), this reduces chunks from 39 to 20, saving ~46ms per run due to fewer structured-clone round-trips. Benchmark results (repomix self-pack, 996 files, 3.8M chars, 5 runs): - Before (100K chunks): 1384ms median - After (200K chunks): 1293ms median - Improvement: ~91ms = ~6.6% Combined with existing batch IPC optimization, total improvement vs baseline is ~156ms = ~10.8%. https://claude.ai/code/session_01NjmXXUzBrB2oe4FD82NpGe --- src/core/metrics/calculateOutputMetrics.ts | 8 ++++---- tests/core/metrics/calculateOutputMetrics.test.ts | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/core/metrics/calculateOutputMetrics.ts b/src/core/metrics/calculateOutputMetrics.ts index 05f97a62f..c2314315e 100644 --- a/src/core/metrics/calculateOutputMetrics.ts +++ b/src/core/metrics/calculateOutputMetrics.ts @@ -2,10 +2,10 @@ import { logger } from '../../shared/logger.js'; import { type MetricsTaskRunner, runTokenCount } from './metricsWorkerRunner.js'; import type { TokenEncoding } from './TokenCounter.js'; -// Target ~100KB per chunk so that each worker task does meaningful tokenization work. -// Previously this was 1000 (number of chunks), which created ~1KB chunks for 1MB output, -// causing ~1000 worker round-trips with ~0.5ms overhead each (~500ms total waste). -const TARGET_CHARS_PER_CHUNK = 100_000; +// Target ~200KB per chunk to balance tokenization throughput and worker round-trip overhead. +// Benchmarks show 200K is the sweet spot: fewer round-trips than 100K with enough chunks +// for good parallelism across available threads (e.g., 20 chunks for 4MB output on 4 cores). +const TARGET_CHARS_PER_CHUNK = 200_000; const MIN_CONTENT_LENGTH_FOR_PARALLEL = 1_000_000; // 1MB export const calculateOutputMetrics = async ( diff --git a/tests/core/metrics/calculateOutputMetrics.test.ts b/tests/core/metrics/calculateOutputMetrics.test.ts index 8a21ca5c0..c7aacd93b 100644 --- a/tests/core/metrics/calculateOutputMetrics.test.ts +++ b/tests/core/metrics/calculateOutputMetrics.test.ts @@ -173,13 +173,13 @@ describe('calculateOutputMetrics', () => { }), }); - // With TARGET_CHARS_PER_CHUNK=100_000, 1.1MB content should produce 11 chunks + // With TARGET_CHARS_PER_CHUNK=200_000, 1.1MB content should produce 6 chunks const chunkSizes = processedChunks.map((chunk) => chunk.length); - expect(processedChunks.length).toBe(11); + expect(processedChunks.length).toBe(6); // All chunks except the last should be exactly TARGET_CHARS_PER_CHUNK for (let i = 0; i < chunkSizes.length - 1; i++) { - expect(chunkSizes[i]).toBe(100_000); + expect(chunkSizes[i]).toBe(200_000); } expect(processedChunks.join('')).toBe(content); // All content should be processed }); From 9e199164e3f72ec01ff7f67fddce3d8295643d5f Mon Sep 17 00:00:00 2001 From: Kazuki Yamada Date: Mon, 6 Apr 2026 16:46:07 +0900 Subject: [PATCH 2/2] fix(metrics): Use 'characters' instead of 'KB' in chunk size comments JS strings use UTF-16 encoding where character count != byte count. Use 'K characters' for technical accuracy. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/core/metrics/calculateOutputMetrics.ts | 4 ++-- tests/core/metrics/calculateOutputMetrics.test.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/metrics/calculateOutputMetrics.ts b/src/core/metrics/calculateOutputMetrics.ts index c2314315e..9b155c0c2 100644 --- a/src/core/metrics/calculateOutputMetrics.ts +++ b/src/core/metrics/calculateOutputMetrics.ts @@ -2,9 +2,9 @@ import { logger } from '../../shared/logger.js'; import { type MetricsTaskRunner, runTokenCount } from './metricsWorkerRunner.js'; import type { TokenEncoding } from './TokenCounter.js'; -// Target ~200KB per chunk to balance tokenization throughput and worker round-trip overhead. +// Target ~200K characters per chunk to balance tokenization throughput and worker round-trip overhead. // Benchmarks show 200K is the sweet spot: fewer round-trips than 100K with enough chunks -// for good parallelism across available threads (e.g., 20 chunks for 4MB output on 4 cores). +// for good parallelism across available threads (e.g., 20 chunks for a 4M character output). const TARGET_CHARS_PER_CHUNK = 200_000; const MIN_CONTENT_LENGTH_FOR_PARALLEL = 1_000_000; // 1MB diff --git a/tests/core/metrics/calculateOutputMetrics.test.ts b/tests/core/metrics/calculateOutputMetrics.test.ts index c7aacd93b..f3ec9f81a 100644 --- a/tests/core/metrics/calculateOutputMetrics.test.ts +++ b/tests/core/metrics/calculateOutputMetrics.test.ts @@ -173,7 +173,7 @@ describe('calculateOutputMetrics', () => { }), }); - // With TARGET_CHARS_PER_CHUNK=200_000, 1.1MB content should produce 6 chunks + // With TARGET_CHARS_PER_CHUNK=200_000, 1.1M character content should produce 6 chunks const chunkSizes = processedChunks.map((chunk) => chunk.length); expect(processedChunks.length).toBe(6);