-
Notifications
You must be signed in to change notification settings - Fork 13.5k
Floating point std::to_chars has a pretty large code size impact #64180
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
Comments
If you're on a target where you have to link against an external libc anyway (which I think includes most mobile apps), the conversion method with the smallest codesize is going to be just "call snprintf". |
@efriedma-quic The code is in the libc++ dylib and currently there is no way to avoid building that. So when using libc's printf you still get these tables. The other option was to add these tables in the headers but that has a compilation overhead. Looking into Looking at dragonbox is indeed on my radar. I saw a post by @jk-jeon a few weeks ago where there were more table size optimizations. I have other things higher on my priority list so it might take some time before I can look into this. |
I meant, you could reimplement to_chars on top of snprintf. |
@mordante Thanks for having an interest in my work. Indeed Dragonbox uses a smaller table than (the reference implementation of) Ryu when both are configured to optimize the table size, and there are two reasons:
@efriedma-quic But can you? How do you find the shortest roundtrippable output using snprintf? |
@jk-jeon thanks for the information! You don't happen to be willing to contribute your algorithm to libc++? I know it's a lot to ask, but you have probably a way better understanding of these kinds of algorithms than any of the regular contributors. We are also still missing I think it could make sense to have a configure-time option to change whether we want a compressed table or not. Though that would mean another configuration for potentially not that much benefit, depending on how much size decrease there actually is when switching to a compressed table. |
First of all, there was a misunderstanding from my side which should be corrected. The vast majority (102kb) of the mentioned 163kb is the table used by Ryu-printf, which is an algorithm for fixed-precision formatting, and is a very different algorithm from Ryu, which is for shortest roundtrippable formatting. Their reference implementations happen to be in the same repo though. I thought the OP was talking about Ryu, but Ryu only uses 10kb-ish table. Unfortunately, the size optimization option provided in Ryu, as far as I know, only compresses this 10kb-ish table so if Ryu-printf is the problem then it's useless. Honestly, I expect that compressing Ryu-printf table will be much harder than Ryu due to how it's designed. The Dragonbox repo does not contain an implementation of any algorithm for fixed-precision formatting, and now I realize that probably @mordante was talking about this one rather than Dragonbox, and I also now realize that, yes, you can replace Ryu-printf with snprintf if the size is a concern. Sorry about the confusion @efriedma-quic. @philnik777 Now, regarding the contribution, it would be my great pleasure, but maybe not in the near future. I deeply appreciate your offer though. I think these floating-point formatting/parsing things are best done with coherently designed set of algorithms to avoid pointless duplication of giant tables and other implementation details. So my plan is to first work on a more full-fledged library that basically covers all options for In case anyone is interested, there is an ongoing effort by @mborland and others of making such a library: https://github.com/cppalliance/charconv As far as I know, the floating-point formatting part of this library is based on my Dragonbox and the other algorithm mentioned above. |
@efriedma-quic as mentioned by others, @jk-jeon I've read multiple of your posts.
I love this idea! libc++ doesn't have Do you know which algorithm you want to use for |
I'll admit I wasn't really thinking about that part. That said, I think I remember reading somewhere about an algorithm for truncating a number to the correct precision using decimal arithmetic... don't remember where I saw it, though. |
Ah, this was a misunderstanding on my side. You're right; the large tables are POW10_SPLIT_2 and POW10_SPLIT, and there's no compressed equivalents. |
Thanks for your kind offer. I'll let you know if I got anything you can help with.
Obviously, I cannot just copy-and-paste Eisel-Lemire, because then I cannot recycle the Dragonbox table. Also I feel like I once upon a time figured that some aspects of Eisel-Lemire is not quite optimal and maybe I can make it better, though I forgot about the details. So probably I will just write my own algorithm based on my understanding of the stuffs, and will not try to strictly mimic Eisel-Lemire. I do not know if the resulting algorithm will be just a minor variation of Eisel-Lemire, or a bit more novel than that. |
As @jk-jeon said I am nearing completion on the development of a charconv library for boost here: https://github.com/cppalliance/charconv. It uses a number of his algorithms, and Lemire's. It is all licensed under the Boost Software License which should be compatible with the LLVM license. If I need to dual-license it in order for you to use it that should be straightforward as well. |
I've measured Ryu to increase the size of libc++ by 163 KiB even when optimizing for size. A lot of that comes from the precomputed tables. That's a substantial size increase for mobile apps.
Some ideas that could help (that I haven't measured yet):
The text was updated successfully, but these errors were encountered: