Skip to content

Conversation

@m4tx
Copy link
Collaborator

@m4tx m4tx commented Nov 24, 2025

No description provided.

@m4tx m4tx force-pushed the model branch 2 times, most recently from e283557 to bb4e565 Compare December 9, 2025 11:05
@m4tx m4tx force-pushed the model-writer branch 2 times, most recently from 61c7929 to ddc6cb1 Compare December 12, 2025 11:02
@m4tx m4tx requested a review from qwandor December 12, 2025 11:02
const LAST_VERSION: u32 = 17;
const LAST_COMP_VERSION: u32 = 16;

pub(crate) fn to_bytes(tree: &DeviceTree) -> Vec<u8> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having all these methods return Vec<u8> results in a lot a temporary allocations and copying. Instead, take a mutable reference to the place where the bytes should be written. This could either be an &mut [u8] (in which case you probably also want a way to compute ahead of time how big the buffer needs to be), or perhaps &mut impl embedded_io::Write to be more general. The latter is implemented for Vec<u8>.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could also just pass &mut Vec<u8> around, right? These are all private functions anyways. Ideally I'd like to avoid adding more dependencies to keep the library lightweight. Computing the exact sizes (which we also need to do for &mut Writer because we need to write the header first) sounds like it could hurt the performance, as this essentially means doing all the writing without actually writing to the buffer (although admittedly it's hard to tell by how much without actually measuring it).

I've changed the code to only allocate one Vec<u8> buffer; let me know if it makes sense.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is better than the previous version, but I still don't think it's a great API. It will also still involve multiple allocations, as the backing buffer of the Vec will be reallocated several times as it is expanded.

Separately, why not make this function a method on DeviceTree? If it's just because you want it in this module, you can have another impl block for DeviceTree here.

Copy link
Collaborator Author

@m4tx m4tx Dec 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I've modified the code then to preallocate the Vec before writing to it. Note that we still allocate in the StringMap's BTreeMap and when writing the FDT string block, but I don't think we can avoid these. Let me know if that's something you had in mind.

The code is also inside impl DeviceTree block now.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still not convinced this is the best approach, but let's go ahead and merge this and I'll send another PR later with some ideas.

Base automatically changed from model to main December 12, 2025 12:46
@m4tx m4tx requested a review from qwandor December 12, 2025 17:37
@qwandor qwandor merged commit aaabd29 into main Dec 16, 2025
25 checks passed
@qwandor qwandor deleted the model-writer branch December 16, 2025 16:24
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.

2 participants