TailMessages: only check first 200 bytes for type field

The type field is near the start of JSONL objects. Scanning the
full object (potentially megabytes for tool_results) was the
bottleneck — TwoWaySearcher dominated the profile.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kent Overstreet 2026-03-22 03:35:40 -04:00
parent e83d0184ea
commit 42bd163942

View file

@ -203,11 +203,12 @@ impl Iterator for TailMessages {
let obj_bytes = &self.mmap[open..=close]; let obj_bytes = &self.mmap[open..=close];
// Quick byte check: skip objects that aren't user/assistant // The "type" field is near the start of top-level objects.
// messages. Avoids serde-parsing megabyte tool_result objects. // Only check the first 200 bytes to avoid scanning megabyte objects.
let is_user = memchr::memmem::find(obj_bytes, b"\"type\":\"user\"").is_some(); let prefix = &obj_bytes[..obj_bytes.len().min(200)];
let is_user = memchr::memmem::find(prefix, b"\"type\":\"user\"").is_some();
let is_assistant = !is_user let is_assistant = !is_user
&& memchr::memmem::find(obj_bytes, b"\"type\":\"assistant\"").is_some(); && memchr::memmem::find(prefix, b"\"type\":\"assistant\"").is_some();
if !is_user && !is_assistant { continue; } if !is_user && !is_assistant { continue; }
let obj: Value = match serde_json::from_slice(obj_bytes) { let obj: Value = match serde_json::from_slice(obj_bytes) {