Skip to content

perf: encode the Typst source straight into native memory - #48

Open
msallin wants to merge 1 commit into
evolvedlight:developfrom
swisspost:feat/source-utf8-native-encode
Open

perf: encode the Typst source straight into native memory#48
msallin wants to merge 1 commit into
evolvedlight:developfrom
swisspost:feat/source-utf8-native-encode

Conversation

@msallin

@msallin msallin commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Encoding.UTF8.GetBytes copied the whole source onto the managed heap for one native call and left it as garbage. The Rust side copies the bytes into an owned String, so the array was only a staging buffer. A 200 KB source measured 200,024 bytes, on the large object heap; it is now encoded into the native buffer directly.

The (pointer, length) contract is unchanged, so embedded NUL bytes still survive. The new byte[1] placeholder goes away with it — it existed only because fixed over an empty array yields a null pointer, which the native side reads as "no in-memory source".

Also moves the native allocations inside the try whose finally releases them. They were made before it, with fontPaths.ToList() over a caller-supplied lazy sequence and JsonSerializer.Serialize in between; either could throw and leak everything allocated up to that point.

Tests: empty source, which pins the null-pointer-versus-empty distinction the placeholder used to carry, and a source above 85 KB with multi-byte characters.

58/58 pass, clean on net8/9/10.

Encoding.UTF8.GetBytes copied the whole source onto the managed heap for the
duration of one native call and left it as garbage afterwards; the Rust side
copies the bytes into an owned String, so the array was only a staging buffer.
A 200 KB source measured 200,024 bytes, on the large object heap. It is now
encoded into the native buffer directly, which also removes the one-byte
placeholder the empty-source case needed to avoid a null pointer.

The native allocations moved inside the try whose finally releases them. They
were made before it, so a throw from the caller-supplied font path sequence or
from serialising the system inputs leaked everything allocated up to that point.
@msallin
msallin force-pushed the feat/source-utf8-native-encode branch from 9609ebc to 8312736 Compare September 6, 2026 19:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant