Skip to content

object_id: back id types by Box<[u8]> instead of Vec<u8> - #9930

Open
martinvonz wants to merge 1 commit into
mainfrom
mz/vmusqpmvorxw
Open

object_id: back id types by Box<[u8]> instead of Vec<u8>#9930
martinvonz wants to merge 1 commit into
mainfrom
mz/vmusqpmvorxw

Conversation

@martinvonz

Copy link
Copy Markdown
Contributor

The ids are immutable, so there is no need to track spare capacity. This makes each id type one usize smaller.

Checklist

If applicable:

  • I have updated CHANGELOG.md
  • I have updated the documentation (README.md, docs/, demos/)
  • I have updated the config schema (cli/src/config-schema.json)
  • I have added/updated tests to cover my changes
  • I fully understand the code that I am submitting (what it does,
    how it works, how it's organized), including any code drafted by an LLM.
  • For any prose generated by an LLM, I have proof-read and copy-edited with
    an eye towards deleting anything that is irrelevant, clarifying anything
    that is confusing, and adding details that are relevant. This includes,
    for example, commit descriptions, PR descriptions, and code comments.

@martinvonz
martinvonz requested a review from a team as a code owner August 6, 2026 18:52
Comment thread lib/src/backend.rs

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

optional: It still may be useful to provide some to_vec(), from_vec() functions so callers can migrate.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The new() function still takes a Vec<u8> and to_bytes() still returns Vec<u8>, so that should be fine. It's actually the Box<[u8]> versions that are missing. We may want to add those and see if we can avoid conversions to/from Vec<u8> in some places.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It's actually the Box<[u8]> versions that are missing. We may want to add those and see if we can avoid conversions to/from Vec<u8> in some places.

Yes, we should probably rename new(Vec<u8>) to from_vec(Vec<u8>).

I have no idea if saving 8 bytes matters, but I'm not against it. If we decide to inline up to 32 or 64 bytes, there's room for a capacity field.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I have no idea if saving 8 bytes matters, but I'm not against it.

I don't know if it matters either, and I don't feel strongly either way.

If we decide to inline up to 32 or 64 bytes, there's room for a capacity field.

Do you mean using something like SmallVec<[u8; 32]>? I suppose that's another option. I don't know how to decide if that's better without someone spending time doing some profiling.

Yes, we should probably rename new(Vec<u8>) to from_vec(Vec<u8>).

Done.

Comment thread lib/src/object_id.rs
$(#[$attr])*
#[derive($crate::content_hash::ContentHash, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
$vis struct $name(Vec<u8>);
$vis struct $name(Box<[u8]>);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It might also be worth considering Arc<[u8]>, since IDs are cloned fairly often. I'm not sure whether the overhead of cloning is higher than the overhead of an atomic reference count though.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good point. I think my answer is the same as above: it's hard to know without someone doing some profiling.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

As far as I can tell, the allocation cost isn't significant. What matters more is the cache locality of things like Vec<TreeValue>.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I am by no means a Rust expert, but I just happened to come across a YouTube video called "Use Arc instead of Vec" by Logan Smith (no link to avoid coming across as spam :p), and in it he provides arguments for always preferring Arc<[T]> over Vec<T> if you need Clone, and preferring Box<[T]> if you don't need Clone. Since Scott said that IDs are cloned a lot, maybe Arc<[T]> would be slightly faster, though presumably it's fairly cheap to copy in a Box<[T]> anyway. The video also did not mention the overhead cost of the atomic count, and I would not know any better either. Food for thought 🙃

The ids are immutable, so there is no need to track spare capacity.
This makes each id type one `usize` smaller.
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.

5 participants