# Automated Data Oriented Design (DOD) transformations?

**URL:** <https://internals.rust-lang.org/t/automated-data-oriented-design-dod-transformations/18011>\
**Category:** language design\
**Created:** [December 21, 2022, 3:42am UTC](https://internals.rust-lang.org/t/automated-data-oriented-design-dod-transformations/18011 "2022-12-21T03:42:46Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![SUPERCILEX](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/supercilex/32/8541_2.png) [@SUPERCILEX](https://internals.rust-lang.org/u/SUPERCILEX)\
**Post date:** [December 21, 2022, 3:42am UTC](https://internals.rust-lang.org/t/automated-data-oriented-design-dod-transformations/18011/1 "2022-12-21T03:42:46Z")

</div>

I think the compiler already does this for the limited case of a single bool in a enum, but I'm wondering if these transformations could be applied more broadly.

For example,

```rust
enum E {
    A(u64, u32, u16, u8, bool),
    B(u64),
}

```

is only 16 bytes even though it should be 24 if the bool wasn't being inlined into the tag. However, adding just a single extra bit to either variant breaks this optimization and makes the type 24 bytes. Are there any technical limitations that would prevent us from using all 8 bits in the tag?

I'm not sure how common these inlinings would be in practice (only useful if the extra byte is going to exceed the alignment boundary), but it'd be neat if this was something we could do.

---

<div class="post-metadata">

**Author:** ![SUPERCILEX](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/supercilex/32/8541_2.png) [@SUPERCILEX](https://internals.rust-lang.org/u/SUPERCILEX)\
**Post date:** [December 21, 2022, 3:45am UTC](https://internals.rust-lang.org/t/automated-data-oriented-design-dod-transformations/18011/2 "2022-12-21T03:45:31Z")

</div>

Ooh, just discovered another fun one:

```rust
enum E {
    A(u64, u32, u16, u8, NonZeroU8),
    B,
}

```

Also 16 bytes by using the niche. Of course it breaks if you add another variant since that requires another bit.

---

<div class="post-metadata">

**Author:** ![kpreid](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kpreid/32/8484_2.png) [@kpreid](https://internals.rust-lang.org/u/kpreid)\
**Post date:** [December 21, 2022, 4:22am UTC](https://internals.rust-lang.org/t/automated-data-oriented-design-dod-transformations/18011/3 "2022-12-21T04:22:14Z")

</div>

> [@SUPERCILEX](#):
>
> Are there any technical limitations that would prevent us from using all 8 bits in the tag?

The language-semantics reason is that it must be possible to take a reference — even `&mut` — to any field of the enum. This can be disabled, currently for `#[repr(packed)]`, but that doesn't enable bit-level packing, and if there was such a bit-packed repr, it won't be the _default_ choice of representation for an enum since that would stop it from being used in the normal Rust fashion where you can take an `&` reference to anything.

---

<div class="post-metadata">

**Author:** ![SUPERCILEX](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/supercilex/32/8541_2.png) [@SUPERCILEX](https://internals.rust-lang.org/u/SUPERCILEX)\
**Post date:** [December 21, 2022, 5:09am UTC](https://internals.rust-lang.org/t/automated-data-oriented-design-dod-transformations/18011/4 "2022-12-21T05:09:42Z")

</div>

Dang, forgot you could do that. So then is the reason the current optimizations are only able to work on a single bit because they're using the tag as the relevant byte when taking a reference? For example, the bool example I showed could have it's tag be 0 if it's A with bool=false, 1 if it's A with bool=true, and 2 if it's B. That still doesn't explain why changing B to be more than 64 bits breaks this though. Maybe a bug?

---

<div class="post-metadata">

**Author:** ![kpreid](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kpreid/32/8484_2.png) [@kpreid](https://internals.rust-lang.org/u/kpreid)\
**Post date:** [December 21, 2022, 2:53pm UTC](https://internals.rust-lang.org/t/automated-data-oriented-design-dod-transformations/18011/5 "2022-12-21T14:53:40Z")

</div>

> [@](#):
>
> So then is the reason the current optimizations are only able to work on a single bit because they're using the tag as the relevant byte when taking a reference? For example, the bool example I showed could have it's tag be 0 if it's A with bool=false, 1 if it's A with bool=true, and 2 if it's B.

Yes — and if you have two `bool` fields, you need two distinct bytes that hold 0 or 1. So two `bool`s can never be packed into one byte.

> That still doesn't explain why changing B to be more than 64 bits breaks this though. Maybe a bug?

No idea. It's not a bug in the sense that no layout optimizations of this sort are _guaranteed,_ but it does seem like it ought to be possible.

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jrose/32/9591_2.png) [@jrose](https://internals.rust-lang.org/u/jrose)\
**Post date:** [December 21, 2022, 5:18pm UTC](https://internals.rust-lang.org/t/automated-data-oriented-design-dod-transformations/18011/6 "2022-12-21T17:18:15Z")

</div>

My guess: u64 alignment means that `(u64, bool)` or `(u64, u8)` is already 16 bytes, but where the last byte is part of the padding and can thus be in any bit pattern; if you assigned over the entire payload for B, it might alter the state of that last byte.

---

<div class="post-metadata">

**Author:** ![SUPERCILEX](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/supercilex/32/8541_2.png) [@SUPERCILEX](https://internals.rust-lang.org/u/SUPERCILEX)\
**Post date:** [December 21, 2022, 8:57pm UTC](https://internals.rust-lang.org/t/automated-data-oriented-design-dod-transformations/18011/7 "2022-12-21T20:57:22Z")

</div>

Neat, thanks!

---

<div class="post-metadata">

**Author:** ![SUPERCILEX](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/supercilex/32/8541_2.png) [@SUPERCILEX](https://internals.rust-lang.org/u/SUPERCILEX)\
**Post date:** [December 21, 2022, 9:01pm UTC](https://internals.rust-lang.org/t/automated-data-oriented-design-dod-transformations/18011/8 "2022-12-21T21:01:36Z")

</div>

Not sure I understand: whatever happens the tag needs to be assigned correctly. Are you saying having padding bytes between the u8 and a tag at the end is a problem?

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jrose/32/9591_2.png) [@jrose](https://internals.rust-lang.org/u/jrose)\
**Post date:** [December 21, 2022, 9:20pm UTC](https://internals.rust-lang.org/t/automated-data-oriented-design-dod-transformations/18011/9 "2022-12-21T21:20:45Z")

</div>

If you could take a mutable reference to _the entire payload_ and assign over it, there wouldn’t be anywhere to also set the tag. But Rust doesn’t let you do the thing I just said, so maybe that’s not the actual explanation.

---

<div class="post-metadata">

**Author:** ![SUPERCILEX](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/supercilex/32/8541_2.png) [@SUPERCILEX](https://internals.rust-lang.org/u/SUPERCILEX)\
**Post date:** [December 22, 2022, 12:26am UTC](https://internals.rust-lang.org/t/automated-data-oriented-design-dod-transformations/18011/10 "2022-12-22T00:26:45Z")

</div>

Oh gotya, maybe that makes sense? I created [Continue performing Data Oriented Design optimization in enums with variants of similar size · Issue #106026 · rust-lang/rust · GitHub](https://github.com/rust-lang/rust/issues/106026) to try and eventually confirm.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 22, 2023, 12:26am UTC](https://internals.rust-lang.org/t/automated-data-oriented-design-dod-transformations/18011/11 "2023-03-22T00:26:59Z")

</div>

Closed on March 22, 2023, 12:26am UTC

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
