-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
core: use FormattingOptions
by reference
#136862
Conversation
Most of the time, the options passed to `Formatter` will be the unmodified default options. The current approach of using the options by-value means that a new `FormattingOptions` structure has to be created every time a formatter is constructed. With this PR, `Formatter` stores the options by-reference, which means that one `FormattingOptions` instance in static memory is enough to create a `Formatter`. In the future (and in particular once rust-lang#119899 has merged), we might even consider removing `fmt::rt::Placeholder` in favour of `FormattingOptions`, which would – in combination with this change – decrease the option-copying even further.
This comment has been minimized.
This comment has been minimized.
@bors try @rust-timer queue |
This comment has been minimized.
This comment has been minimized.
core: use `FormattingOptions` by reference Most of the time, the options passed to `Formatter` will be the unmodified default options. The current approach of using the options by-value means that a new `FormattingOptions` structure has to be created every time a formatter is constructed. With this PR, `Formatter` stores the options by-reference, which means that one `FormattingOptions` instance in static memory is enough to create a `Formatter`. In the future (and in particular once rust-lang#119899 has merged), we might even consider removing `fmt::rt::Placeholder` in favour of `FormattingOptions`, which would – in combination with this change – decrease the option-copying even further. CC rust-lang#118117 `@EliasHolzmann`
☀️ Try build successful - checks-actions |
This comment has been minimized.
This comment has been minimized.
Finished benchmarking commit (3bd291a): comparison URL. Overall result: ❌✅ regressions and improvements - please read the text belowBenchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. While you can manually mark this PR as fit for rollup, we strongly recommend not doing so since this PR may lead to changes in compiler perf. Next Steps: If you can justify the regressions found in this try perf run, please indicate this with @bors rollup=never Instruction countThis is the most reliable metric that we have; it was used to determine the overall result at the top of this comment. However, even this metric can sometimes exhibit noise.
Max RSS (memory usage)Results (primary -0.9%, secondary -4.2%)This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
CyclesResults (primary -14.5%, secondary -1.1%)This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
Binary sizeResults (primary 0.0%, secondary 0.0%)This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
Bootstrap: missing data |
If it makes any measurable difference, this seems fine. However, ideally, we'd make The problem is that Perhaps we can all agree that it's fine to reduce it to an u32 or u16 or u8. If we then also reserve That would technically be a breaking change, though. |
width and precision are returned by value, right? So moving None into the flags field would not be breaking? Reducing the maximums would be, but suppose we made one of the flags "use the remaining fields as a pointer to a larger structure"? And then you couldn't use values bigger than u16 without an implicit allocation, which seems like a reasonable restriction. |
This is the information that FormattingOptions contains:
Everything except the last two can simply fit in a If we keep them as full |
Then we'd still need to make the structure two words in size rather than one, to be able to store the pointer somewhere. We could do some alignment trickery to steal one or two bits of the pointer, and move all the flags into the allocated part to keep |
Checking a single bit doesn't seem that awful, if everything else along that branch is a cold path. I expect we would probably win on net by making the structure a u64. (But as always, benchmarks speak louder than words.) |
Note that all of this also needs to work in no_std situations, where we cannot allocate or anything like that. And we should pay some attention to binary size too. |
I'm up for trying to apply the restriction to u16 across the board. This was an idea for a fallback if that restriction breaks something: we could say that if you have alloc you can use more than u16 and otherwise you can't. |
That doesn't make much sense. We don't even have a mechanism for that. I'll do a crater run for the reduction to u16. |
Running the experiment here: #136932 |
r? @m-ou-se |
I much prefer these approaches, so I'm closing this. |
Thanks for the mention @joboet! And sorry for me somehow completely missing your point in #118117 (comment) :) Regarding the discussion on making |
Most of the time, the options passed to
Formatter
will be the unmodified default options. The current approach of using the options by-value means that a newFormattingOptions
structure has to be created every time a formatter is constructed. With this PR,Formatter
stores the options by-reference, which means that oneFormattingOptions
instance in static memory is enough to create aFormatter
. In the future (and in particular once #119899 has merged), we might even consider removingfmt::rt::Placeholder
in favour ofFormattingOptions
, which would – in combination with this change – decrease the option-copying even further.CC #118117 @EliasHolzmann