-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Printf get container #1982
Printf get container #1982
Conversation
Thanks for the PR. Please fix formatting in the PR description and post benchmark results as text, not as image. |
Thanks for getting to the PR so quickly. Just tell me if you'd like to have the json output as well. |
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.
The idea looks fine but I think you should use fmt::detail::write
instead of reimplementing container/buffer detection.
d566465
to
c4f62bf
Compare
I'll have to get back to this next week. Just to be sure I'm not operating on wrong assumptions: The following two benchmarks should have very similar results, right? void long_printf_format_string(benchmark::State& state) {
std::string format_string = std::string(state.range(0), 'A') + "%s";
std::string message = "Hi";
for (auto _ : state) {
benchmark::DoNotOptimize(fmt::sprintf(format_string, message));
};
}
BENCHMARK(long_printf_format_string)->Arg(10)->Arg(100)->Arg(1000)->Arg(10000);
void long_fmt_format_string(benchmark::State& state) {
std::string format_string = std::string(state.range(0), 'A') + "{}";
std::string message = "Hi";
for (auto _ : state) {
benchmark::DoNotOptimize(fmt::format(format_string, message));
};
}
BENCHMARK(long_fmt_format_string)->Arg(10)->Arg(100)->Arg(1000)->Arg(10000); On the branch (c4f62bf) the version with printf becomes quite a bit faster than the fmt version from 100 characters:
|
Somewhat similar. The printf numbers look suspicious both compared to format and your earlier results. I recommend checking that the modified version produces the correct output. |
I finally got a chance to look into this and the results are indeed correct. As it turned out
Thanks for catching this! My earlier comment about using |
… a fmt::basic_memory_buffer character by character instead of using fmt::basic_memory_buffer::append
c4f62bf
to
104b3de
Compare
I have edited the top message to reflect the latest state, I hope this isn't too confusing. |
test/printf-test.cc
Outdated
EXPECT_EQ((truncated_printf_context( | ||
EXPECT_EQ(expected_size, | ||
(truncated_printf_context( | ||
fmt::detail::truncating_iterator<backit>(it, 0), format_string, | ||
fmt::make_format_args<truncated_printf_context>(format_arg)) | ||
.format() | ||
.count()), | ||
expected_size); | ||
.count())); |
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 change seems unnecessary, please revert.
test/printf-test.cc
Outdated
TEST(PrintfTest, PrintfAppendToBuffer) { | ||
using backit = std::back_insert_iterator<fmt::basic_memory_buffer<char>>; | ||
using context = fmt::basic_printf_context<backit, char>; | ||
|
||
const auto format_string = "%s"; | ||
const char* format_arg = "Hello"; | ||
fmt::basic_memory_buffer<char> buffer; | ||
context(std::back_inserter(buffer), format_string, | ||
fmt::make_format_args<context>(format_arg)) | ||
.format(); | ||
|
||
std::string result(std::begin(buffer), std::end(buffer)); | ||
|
||
EXPECT_EQ(std::string("Hello"), result); | ||
} |
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.
What is the purpose of this test? We should avoid adding more tests that rely too much on implementation details.
…ual in PrintfDetermineOutputSize
test/printf-test.cc
Outdated
const auto expected_size = fmt::sprintf(format_string, format_arg).size(); | ||
const auto expected_size = 5; | ||
|
||
EXPECT_EQ((truncated_printf_context( | ||
EXPECT_EQ(expected_size, fmt::sprintf(format_string, format_arg).size()); | ||
|
||
EXPECT_EQ(expected_size, | ||
(truncated_printf_context( | ||
fmt::detail::truncating_iterator<backit>(it, 0), format_string, | ||
fmt::make_format_args<truncated_printf_context>(format_arg)) | ||
.format() | ||
.count()), | ||
expected_size); | ||
.count())); |
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 also looks unrelated, please revert (possibly submitting a separate PR to improve tests).
…the code changes directly
Thank you! |
Thanks for your patience, I will try to get future pull requests to be more focused. |
I agree that my contributions are licensed under the {fmt} license, and agree to future changes to the licensing.
This affects the performance of fmt::sprintf in the case where the format string is at least on the order of 100 characters long.
The benchmark:
The benchmark numbers change as follows:
master (60dc273)
branch (104b3de)