-
Notifications
You must be signed in to change notification settings - Fork 4.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
Support C++20 std::format as an alternative to fmtlib #2170
Conversation
Thanks.See my comments:
|
I had to wait for AppVeyor to catch up to all my commits to see what was fixed by the follow ups, will look at them soon.
On MSVC, std::format will behave much faster with std::string than with memory_buffer (or anything else) especially with longer strings because it implements special optimizations for it (comparing against fmtlib 8.0.1):
https://gist.github.com/sylveon/6e6347e2975d7fba0ebad039f233f52a Generally, allocation time is trivially short compared to the operation of formatting strings itself.
I already tried reducing those as most as possible. What's remaining is mostly in test code. Is it possible to just overload
MSVC's is complete, and local testing shows everything seems to work fine with it. Clang seems to be on its way to supporting as well. And I imagine GCC is probably not that far out either. I wrote this assuming P2216 so it should be compatible with all implementations once they are out. |
Interesting. what kind of optimizations? Seems that the back inserter benchmark use he same backing string object for all the iterations so no wonder it is so fast. Allocation happened only once (still, I dont understand why it is x5 faster than fmt) |
It recognizes that you passed
The memory_buffer benchmark does the same, and memory_buffer::clear doesn't get rid of the backing allocation if any, just sets the size back to 0. |
Right but the format string under test is bigger than 250 so they both allocate. I suggest benching with 100-200 chars and of course not reuse the backing string object across the iterations. |
Using a 94 characters format string, and creating a string/memory_buffer in the lambda instead of globally gives this:
The same benchmark using wide characters:
std::format is a tiny bit faster on strings than on memory_buffer, however I'm not sure why fmtlib suffers so much on the string here (but it happens reliably accross runs). These where built with /O2 (max optimization on MSVC). fmtlib + fmt::memory_buffer is obviously best case for short strings, but ultimately this 150ns difference won't be what makes or break spdlog. It's still plenty fast (and with wchar_t, actually faster). |
So to summarize for MSVC, using I wonder if we could optimize the heap allocation of the std::string though. Maybe reuse/extract fmt's |
Yeah, a custom allocator could work, it seems. Could be a bit tricky when a string is moved, but usage of memory_buf_t avoids this already. |
Probably would be easier to reuse/extract fmt's memory_buffer. Could be done on later PR though. Once you fix the tests I can merge, so let me know @sylveon |
Sure thing. Extracting the memory_buffer from fmt won't make it anymore faster I believe however. |
… use fmt::runtime in test_errors
Don't mind the mess of commits, just fixing things and letting the CI validate it. Feel free to squash all of this when merging. |
Seems like the Travis CI build doesn't work anymore: https://app.travis-ci.com/github/gabime/spdlog/requests |
fixed the travis ci.. |
Changes requested have been done @gabime The Windows builds are succeeding, but the Travis CI builds are failing, seemingly because of changes recently introduced in |
Merged. Thanks @sylveon ! |
The
with @sylveon, what version of {fmt} are you using and what are the full compiler options? It seems that at least |
I am using fmt 8.0.1 with MSVC 19.30.30705 (VS 17.1 preview 1). The full compiler options are:
Both NDEBUG and /O2 are there. |
Would be interesting to investigate why perf on msvc is so bad compared to clang's. Could be some easy optimization opportunities. |
P2508R1, if merged, will expose std::basic-format-string as a concrete type, allowing spdlog to also support compile-time verification of format strings with std::format, bringing it up to par with fmtlib |
This, when using C++20 mode, allows spdlog to use std::format instead of fmtlib, making spdlog effectively standalone. Compile-time format string checking is the only missing feature compared to using fmtlib, because in std::format, std::format_string was made exposition-only so user code can't access/use it.