From 3a86677126615a163b5c42b2234fdbb6404a07fd Mon Sep 17 00:00:00 2001 From: Aaron O'Mullan Date: Thu, 15 Aug 2024 17:09:40 +0900 Subject: [PATCH] perf(ts): simple monomorphic message parse --- typescript/core/src/McapStreamReader.ts | 12 ++++++++++-- typescript/core/src/parse.ts | 25 +++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/typescript/core/src/McapStreamReader.ts b/typescript/core/src/McapStreamReader.ts index 6ed8292ce..e32c5a7e6 100644 --- a/typescript/core/src/McapStreamReader.ts +++ b/typescript/core/src/McapStreamReader.ts @@ -2,7 +2,7 @@ import { crc32 } from "@foxglove/crc"; import Reader from "./Reader"; import { MCAP_MAGIC } from "./constants"; -import { parseMagic, parseRecord } from "./parse"; +import { monoParseMessage, parseMagic, parseRecord } from "./parse"; import { Channel, DecompressHandlers, McapMagic, TypedMcapRecord, TypedMcapRecords } from "./types"; type McapReaderOptions = { @@ -233,7 +233,15 @@ export default class McapStreamReader { const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength); const chunkReader = new Reader(view); let chunkRecord; - while ((chunkRecord = parseRecord(chunkReader, this.#validateCrcs))) { + while (true) { + if (chunkRecord = monoParseMessage(chunkReader)) { + yield chunkRecord; + continue; + } + chunkRecord = parseRecord(chunkReader, this.#validateCrcs) + if (!chunkRecord) { + break; + } switch (chunkRecord.type) { case "Unknown": break; diff --git a/typescript/core/src/parse.ts b/typescript/core/src/parse.ts index 95d010575..026fd2bda 100644 --- a/typescript/core/src/parse.ts +++ b/typescript/core/src/parse.ts @@ -417,3 +417,28 @@ function parseDataEnd(reader: Reader, recordLength: number): TypedMcapRecord { dataSectionCrc, }; } + + +export function monoParseMessage(reader: Reader): TypedMcapRecord | undefined | null { + const RECORD_HEADER_SIZE = 1 /*opcode*/ + 8; /*record content length*/ + if (reader.bytesRemaining() < RECORD_HEADER_SIZE) { + return undefined; + } + const start = reader.offset; + const opcode = reader.uint8(); + const recordLength = reader.uint64(); + + if (opcode !== Opcode.MESSAGE) { + reader.offset = start; // Rewind to the start of the record + return null; + } + + const recordLengthNum = Number(recordLength); + + if (reader.bytesRemaining() < recordLengthNum) { + reader.offset = start; // Rewind to the start of the record + return undefined; + } + + return parseMessage(reader, recordLengthNum); +}