[GH-ISSUE #1383] Error types are enormous #659

Closed
opened 2026-03-15 23:43:38 +03:00 by kerem · 4 comments
Owner

Originally created by @saethlin on GitHub (Feb 23, 2021).
Original GitHub issue: https://github.com/hickory-dns/hickory-dns/issues/1383

I'm opening this mostly as a record that I've noticed this and it's not great. Please rename this if y'all have a better description.
I've now come across this in two places:

  1. Many chains of movaps in the Name parsing code, because every function returns a Result where the Ok payload is tiny but the Err payload is huge, so every fallible function call relocates a bunch of dead data around. Knocking ProtoError down to 8 bytes is significant enough to be visible in a flamegraph.

  2. In an internal codebase, we have a ResolveErrorKind in a struct which totals 144 bytes, 80 of which are the ResolveErrorKind. This is large enough that LLVM emits a memcpy to move this struct. I suspect this happens at some point in this project as well.

In case 1 for the moment I boxed the internals of ProtoError. That's a nifty optimization if creating errors truly is a cold path (it is in my current use case), but if errors are at some point used to indicate a condition that's close to common, it could be quite bad indeed.

Originally created by @saethlin on GitHub (Feb 23, 2021). Original GitHub issue: https://github.com/hickory-dns/hickory-dns/issues/1383 I'm opening this mostly as a record that I've noticed this and it's not great. Please rename this if y'all have a better description. I've now come across this in two places: 1. Many chains of `movaps` in the `Name` parsing code, because every function returns a `Result` where the `Ok` payload is tiny but the `Err` payload is huge, so every fallible function call relocates a bunch of dead data around. Knocking `ProtoError` down to 8 bytes is significant enough to be visible in a flamegraph. 2. In an internal codebase, we have a `ResolveErrorKind` in a struct which totals 144 bytes, 80 of which are the `ResolveErrorKind`. This is large enough that LLVM emits a `memcpy` to move this struct. I suspect this happens at some point in this project as well. In case 1 for the moment I boxed the internals of `ProtoError`. That's a nifty optimization if creating errors truly is a cold path (it is in my current use case), but if errors are at some point used to indicate a condition that's close to common, it could be quite bad indeed.
kerem 2026-03-15 23:43:38 +03:00
Author
Owner

@bluejekyll commented on GitHub (Feb 23, 2021):

I'm definitely open to reducing the size of the error types, I'm guessing a quick win would be to eliminate some of the wrapped types from dependencies, that are probably not relevant to down stream use cases.

<!-- gh-comment-id:783805492 --> @bluejekyll commented on GitHub (Feb 23, 2021): I'm definitely open to reducing the size of the error types, I'm guessing a quick win would be to eliminate some of the wrapped types from dependencies, that are probably not relevant to down stream use cases.
Author
Owner

@trinity-1686a commented on GitHub (May 6, 2021):

Wrapped types from dependencies might not be the culprits, with no features enabled, trust_dns_resolver::error::ResolveErrorKind appears to be 296 bytes (main, default features), removing ResolveErrorKind::NoRecordsFound make it 32 bytes. NoRecordsFound contains a Query (96 bytes) and an Option<SOA> (184 bytes). Having a Box<Query> and a Option<Box<SOA>> instead would make the enum 32 bytes again, at the cost of one to two allocations

<!-- gh-comment-id:833683750 --> @trinity-1686a commented on GitHub (May 6, 2021): Wrapped types from dependencies might not be the culprits, with no features enabled, `trust_dns_resolver::error::ResolveErrorKind` appears to be 296 bytes (main, default features), removing `ResolveErrorKind::NoRecordsFound` make it 32 bytes. `NoRecordsFound` contains a `Query` (96 bytes) and an `Option<SOA>` (184 bytes). Having a `Box<Query>` and a `Option<Box<SOA>>` instead would make the enum 32 bytes again, at the cost of one to two allocations
Author
Owner

@djc commented on GitHub (May 6, 2021):

Nice, that sounds like an obvious win!

<!-- gh-comment-id:833693546 --> @djc commented on GitHub (May 6, 2021): Nice, that sounds like an obvious win!
Author
Owner

@qm3ster commented on GitHub (Nov 29, 2021):

Why not a Box<(Query, Option<SOA>)> 👀

<!-- gh-comment-id:981482228 --> @qm3ster commented on GitHub (Nov 29, 2021): Why not a `Box<(Query, Option<SOA>)>` 👀
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/hickory-dns#659
No description provided.