-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimize text_style
using bit packing
#4363
base: master
Are you sure you want to change the base?
Conversation
In preparation for optimizing `text_style`.
-> text_style { | ||
return lhs |= rhs; | ||
} | ||
|
||
FMT_CONSTEXPR auto operator==(text_style rhs) const noexcept -> bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
operator==
and operator!=
should really be friends, but I ran into this GCC bug when doing that.
// bit is impossible in that case, because 00 (unset color) means the | ||
// 24 bits that precede the discriminator are all zero. | ||
// | ||
// This test can be applied to both colors simultaneously. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a very bit hacky algorithm; I hope the detailed explanation compensates for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR! Overall LGTM, just one minor comment inline.
return (value_ & (1 << 25)) != 0; | ||
} | ||
|
||
FMT_CONSTEXPR auto get_value() const noexcept -> uint32_t { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest dropping get_
here.
// We do that check by adding the styles. Consider what adding does to each | ||
// possible pair of discriminators: | ||
// 00 + 00 = 000 | ||
// 01 + 00 = 001 | ||
// 11 + 00 = 011 | ||
// 01 + 01 = 010 | ||
// 11 + 01 = 100 (!!) | ||
// 11 + 11 = 110 (!!) | ||
// In the last two cases, the ones we want to catch, the third bit——the | ||
// overflow bit——is set. Bingo. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clever =)
One potential concern is the ABI but it seems to be OK because all the functions involved are inline or templated. |
Currently,
text_style
takes up 20 bytes, but we can pack it into 8.First, a side benefit of that is a smaller and faster implementation of
text_style::operator|
(before-and-after), but that function I imagine is usually evaluated at compile-time anyway.The main benefit is reduced binary size per function call using colors. This comes from two factors:
text_style
through registers (before-and-after); andstyled_arg
becomes smaller, so less data needs to be copied around (before-and-after).This absolutely breaks ABI. (Should the
v11
namespace be bumped tov12
?) I'm actually not sure if it breaks API;it changes the API of
detail::color_type
—an internal type, you would think—but one that's part of the public interface oftext_style
.The first commit adds more color tests, because I don't feel the existing suite is comprehensive enough to prove that this change doesn't affect semantics.