-
Notifications
You must be signed in to change notification settings - Fork 11.9k
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
[libc++] Feature Request - Code tweaks and build flags to produce smaller binaries when using <format> on embedded systems #93646
Comments
See https://reviews.llvm.org/D134036 although I didn't found why a |
I don't recall either and maybe it's no longer/not needed. I feel this request has merits, however I think we should look at the bigger picture. If no floating-point is available we should not have |
I agree about the big picture. I think a lot of the requests in this issue make sense. IMO if we want to make progress on this, we would need someone to write a short RFC explaining how we're going to tackle this, what is going to be affected and how, etc. I'm going to un-assign you for now since you don't think you'll have time to work on this. @BlamKiwi if you have interest for pursuing this, I think that is the most likely way for this issue to make progress. |
@mordante Are you suggesting that you would prefer a compile flag to just disable float support entirely in libc++? I agree that would probably be the useful baseline. The question would then be should disabling just float The pain point is paying for float formatting when you're not actually formatting floats. It is still nice to be able to prototype math with floating point values before moving to something like fixed point arithmetic. I can understand not wanting to support this edge-case though since its pretty niche. Or to state it more plainly, implement a solution in such a way that supporting floats is orthogonal to picking different code-paths to optimize size. @ldionne Regarding to what the consequences are to hard disabling float support, I think the C world provides the most useful example. On the C++ side, there's annoying edge cases like Regarding the other minor optimizations, I assume explicit build flags for modifying behaviour are preferred over compiler flags. e.g., Adding something like |
@BlamKiwi If there is a way to "delay" the instantiation of format for floating point until when we actually need it, then this could be a change we implement while being conforming today, without considering the larger change about floating points. But I'm not certain that's feasible. Another option worth considering is stuff like link-time optimization. If you want to reduce code size, perhaps this can help dead-strip code paths in format that are never used? |
We already use LTO where possible. I will take a second look though. Given how simple the other fixes are, it would be good to get an answer for this. |
IMO no.
Only disabling it for |
I think this is where the misunderstanding is coming from. Embedded work largely uses LTO,
|
Here you describe your use-case and the feature you describe perfectly fits your use-case. However in general we try to add features that are usable for a larger set of users. That's why I don't want to add a special case for your use-case. The next user might want to use shared objects and ostreams but without floating-point support. |
That's fine. What I'm wanting to pursue is an improvement to The main issue with your current implementation is you defer I need to investigate some of the code output a bit more, but it should be possible (in a standards compliance sense) to add a private field to This change would trade-off some runtime overhead for minimizing code size, so I would guard this implementation with a build flag. Something along the lines of EDIT: I'm not saying that removing float support from libc++ as an explicit flag is a bad idea. More that improving codegen for |
I agree if you have a way to improve the codegen of |
See the associated merge request for the main code size optimization. The overhead of using pointer dispatch is ~5% on my laptop. 5% could be significant for some users, so it's probably worth guarding this with a build flag. The benefit is that only formatters actually used get instantiated. I still need to look at the escape functions to get rid of the basic_string usage. Unfortunately the only practical way to remove the use of a temporary buffer would be to iterate over the string twice. Once to count the escaped printable string width and the second time to actually escape and pad the string. |
I've been full tilt at work and haven't had the time to look at this further. I just wanted to point out this blog post by the author of fmtlib outlining what the size savings can be for a similar set of optimizations. EDIT: notably the |
We currently use an internal format library that's a "lean" implementation of the standard for embedded devices. I've been trying to test libc++
<format>
on embedded systems with very little RAM. There's some tweaks that can be made to make libc++ a bit leaner.The C++ standard specifies that
float
,double
andlong double
are explicitly listed types instd::basic_format_arg
. This causes the compiler to pull in all float formatting code and associated lookup tables. This can cause binaries to bloat by >200KB even though it's never used. It is a common feature of embedded libc implementations to provide a compile option to disable float support in printf/scanf. It would be nice if libc++ provided a build flag to disable float types in<format>
or somehow map floats to thehandle
type to implement a compiler firewall.<charconv>
uses lookup tables or dedicated code paths to efficiently convert base 10, base 2, etc. It would be good if optimized codepaths were guarded by__OPTIMIZE_SIZE__
(or equivalent libc++ define) to prevent bringing in this code.__throw_invalid_option_format_error
and__throw_invalid_type_format_error
usebasic_string
and causes the contents ofstring.cpp
to be pulled in. If exceptions are disabled, it would be nice if this message was simplified to a simple c string.__format_escaped_char
and__format_escaped_string
use abasic_string
instead of just passing through the output iterator. Is there a reason this is the case? Directly passing in the iterator would preventbasic_string
usage where it would otherwise not be used.The text was updated successfully, but these errors were encountered: