Copying struct value data partially

I have structs with a number of fields. All simple value types or very small value type arrays.
The first few I want to copy, the last few not, because they are recalculated anyway.
Now can I do somehow a rust-safe mem-copy until some field?
There are low-level things like alignment and field-order which I do not yet know precisely.
This is one of them:

pub struct StateInfo
{
    // copy
    pub pawnkey: u64,
    pub rule_50: i16,
    pub ep_square: Square,
    pub castling_rights: u8,
    pub last_move: Move,
    pub moved_piece: Piece,
    pub captured_piece: Piece,
    // don't copy
    pub hashkey: u64,
    pub checkers: u64,
    pub pinned: [u64; 2],
    pub pinners: [u64; 2],
    pub repetition_count : i16,
}

The other one is bigger and I have like 4 specialized methods for cloning etc. which makes me duplicating code which I don't like. And I could forget some field when I add one :slight_smile:
The 'address' safety is most important of course. No low level hacking.

This isn’t possible even in principle unless the struct is annotated with #[repr(C)] because the default Rust repr allows the compiler to arbitrarily reorder struct fields and the layout is unspecified in all other ways too.

With C repr what you want should in principle be possible with offset_of! and std::ptr::copy, but would very much involve unsafe and is certainly not recommended. Consider simply splitting the "copied" part into its own struct. Or just copying the whole thing, it’s not like a few bytes of extra copying matters, unless you’re trying to do it millions of times per second.

Sounds like you're copying a field at a time. Do you know about the Copy trait? You can put #[derive(Copy, Clone)] at the top of your struct and then just copy the whole thing, very efficiently. The size of the fields you're referring to are very small.

For explicitly setting some fields and copying the others, do you know about the struct update syntax?

Actually currently 540 million times per second. That is why I am asking.

The copy trait I know. Currently I am using clone() and default().
The space is already there in a vector with enough capacity. (Edit: lying here: it is pushed.)

For explicitly setting some fields and copying the others, do you know about the struct update syntax?
Nope I did not know this one!

If it's always the same set of fields, you can...

// naming is hard
#[derive(Copy, Clone)]
pub struct StateData {
    pub pawnkey: u64,
    pub rule_50: i16,
    pub ep_square: Square,
    pub castling_rights: u8,
    pub last_move: Move,
    pub moved_piece: Piece,
    pub captured_piece: Piece,
}

// derive what you want
#[derive(Copy, Clone)]
pub struct StateInfo {
    pub data: StateData,
    pub hashkey: u64,
    pub checkers: u64,
    pub pinned: [u64; 2],
    pub pinners: [u64; 2],
    pub repetition_count : i16,
}

And then the StateData fields will "stay together" (in some order) and you can copy them as one assignment.

I'm not sure from your OP if this is useful advice or not.


You could attempt to pre-allocate dummy values and otherwise reuse previously-used parts of your Vec by keeping track of how many elements are still logically valid (instead of popping / truncating). Then instead of pushing you overwrite the appropriate v[idx].data. It's definitely "benchmark to see if it helped or hurt" territory.

That seems a reasonably good idea to check! Thanks. Will take some time but i will let know the results.

Ok I created a little test using pre-allocation.
The alternative way is at least 1.5 times faster.
I added in some nonsense to ensure (i hope) things are not optimized away.

comments welcome. the test is of course not perfect but gives - i think - a reasonable indication.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.