Skip to content

Use packed struct with bitfields to shrink all member modes down to 32-bits#236

Merged
MatthieuDartiailh merged 4 commits intonucleic:mainfrom
frmdstryr:member-changes
Jan 21, 2025
Merged

Use packed struct with bitfields to shrink all member modes down to 32-bits#236
MatthieuDartiailh merged 4 commits intonucleic:mainfrom
frmdstryr:member-changes

Conversation

@frmdstryr
Copy link
Contributor

@frmdstryr frmdstryr commented Jan 21, 2025

All of the modes can fit into 32 bits. This shrinks the member struct down to 128 bytes (from 144) with an alignment of 8.

The compiler also nicely does all the bit fiddling.

Copy link
Member

@MatthieuDartiailh MatthieuDartiailh left a comment

Choose a reason for hiding this comment

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

I personally love getting rid off the manual masking.

Out of curiosity what is the advantage to move modes and index at the end of the Member struct ?

@codecov
Copy link

codecov bot commented Jan 21, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 97.67%. Comparing base (c365c61) to head (d198654).
Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #236   +/-   ##
=======================================
  Coverage   97.67%   97.67%           
=======================================
  Files          24       24           
  Lines        1074     1074           
  Branches      162      162           
=======================================
  Hits         1049     1049           
  Misses         12       12           
  Partials       13       13           

@frmdstryr
Copy link
Contributor Author

frmdstryr commented Jan 21, 2025

My understanding is compilers will insert padding bytes depending on the size of fields and alignment. So if you have a struct like

struct Foo {
   uint64_t a;
   uint32_t b; 
   uint64_t c;
};

Unless it is packed the compiler might/will insert 4 padding bytes after b so all fields are 8 byte aligned. By sorting fields by their size it minimizes any padding.

Edit: This is why the sizeof(Member) shrunk to 128 bytes from 144 even though only 12 bytes were removed.

@frmdstryr
Copy link
Contributor Author

I just realized it works using

PACK(struct MemberModes
{
    GetAttr::Mode getattr: 4;
    PostGetAttr::Mode post_getattr: 3;
    SetAttr::Mode setattr: 4;
    PostSetAttr::Mode post_setattr: 3;
    DefaultValue::Mode default_value: 4;
    Validate::Mode validate: 5;
    PostValidate::Mode post_validate: 3;
    DelAttr::Mode delattr: 3;
    GetState::Mode getstate: 3;
});

So the get/set methods could just all be dropped.

@sccolbert
Copy link
Member

Neat trick! I'll remember this next time I need bitfields.

@MatthieuDartiailh MatthieuDartiailh merged commit 54adc3f into nucleic:main Jan 21, 2025
18 checks passed
@frmdstryr frmdstryr deleted the member-changes branch January 21, 2025 19:00
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.

3 participants