Problem
Currently the adbc_core::Error struct contains all the fields (message, status, vendor code etc), and it is directly embedded in adbc_core::Result<T>. That means regardless of sizeof(T), adbc_core::Result<T> is always at least sizeof(Error), which is large.
This makes applications pay a lot of stack frame space for the cold error handling path since every Result is big.
In concrete terms
On my ARM Mac:
So currently the error is 64 bytes large whereas a pointer is only 8.
Solution
Change it to something like
pub struct Error(Box<ErrorInner>);
pub struct ErrorInner {
message: String,
// ...
}
impl Error {
pub fn message(&self) -> &str {
&self.0.message
}
// ....
}
Now sizeof(Error) is effectively the size of a thin pointer. The downside is that this requires an extra allocation and dereference on every error, but I assume that's okay since errors are (hopefully) in the cold path.
Note that this will be a massive breaking change since currently all the fields in Error are pub so virtually everyone doing error handling based on those public fields will need to change their code to use accessors instead. We'll also need a constructor and people will need to move away from manually initializing the struct.
The current workaround
Write a wrapper to all methods of the driver manager that returns a custom error type that does the wrapping for you.
The Rust driverbase of ADBC Foundry already does that: https://github.com/adbc-drivers/driverbase-rs/blob/fe2738281cae9a2a92c59cc8c4d0822395187d04/driverbase/src/error.rs#L19
Edits
EDIT1: Added MacOS size comparison
Problem
Currently the
adbc_core::Errorstruct contains all the fields (message, status, vendor code etc), and it is directly embedded inadbc_core::Result<T>. That means regardless ofsizeof(T),adbc_core::Result<T>is always at leastsizeof(Error), which is large.This makes applications pay a lot of stack frame space for the cold error handling path since every
Resultis big.In concrete terms
On my ARM Mac:
So currently the error is 64 bytes large whereas a pointer is only 8.
Solution
Change it to something like
Now
sizeof(Error)is effectively the size of a thin pointer. The downside is that this requires an extra allocation and dereference on every error, but I assume that's okay since errors are (hopefully) in the cold path.Note that this will be a massive breaking change since currently all the fields in
Errorarepubso virtually everyone doing error handling based on those public fields will need to change their code to use accessors instead. We'll also need a constructor and people will need to move away from manually initializing the struct.The current workaround
Write a wrapper to all methods of the driver manager that returns a custom error type that does the wrapping for you.
The Rust
driverbaseof ADBC Foundry already does that: https://github.com/adbc-drivers/driverbase-rs/blob/fe2738281cae9a2a92c59cc8c4d0822395187d04/driverbase/src/error.rs#L19Edits
EDIT1: Added MacOS size comparison