-
Notifications
You must be signed in to change notification settings - Fork 21
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
feat: Custom OStream replacement #267
base: master
Are you sure you want to change the base?
Conversation
if (storage_) { | ||
auto* const begin = static_cast<char*>(storage_.get()); | ||
setp(begin, begin + MaxN); | ||
if (storage_ != nullptr) [[likely]] { |
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.
Whilst I realise this is probably a hangover from the previous impl, why is there a need for a nullptr storage_ ? If we could avoid supporting this we wouldn't need to check the storage_ ptr for nullptr-ness.
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.
Yes, hangover from prev impl.
If we could avoid supporting this we wouldn't need to check the storage_ ptr for nullptr-ness.
Yes, good point. I will try to address this in a follow-up PR. Existing code may rely on this behaviour, so will have to investigate.
toolbox/util/OStreamBase.hpp
Outdated
DerivedT& OStreamBase<DerivedT>::put_data(const char* data, std::size_t data_size) noexcept | ||
{ | ||
char* buf = prepare_space(data_size); | ||
assert(buf != nullptr); |
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.
asserting prepare_space() always returns non-nullptr means all implementations of do_prepare_space() will adhere to this contract. Do they?
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 is not clear to me. Sometimes you assert() non-nullptr-ness, sometime you check as if it's not a given that non-nullptrs are returned.
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.
asserting prepare_space() always returns non-nullptr means all implementations of do_prepare_space() will adhere to this contract. Do they?
No, some implementations have buffers of fixed size which can be fully used up -- in which case they return nullptr (e.g. OStaticStream uses a stack allocated buffer of N bytes)
The assert here is mainly to catch accidental small buffer sizes. Some lpfixgw codecs use ostreams with a fixed buffer size. If that buffer size was too small, it should ideally be caught before it reaches prod.
But yes, it is not part of the contract, implementations are allowed to return nullptr, so strictly speaking the assert should not be there.
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.
I would suggest removing the assert as it's confusing. The assert is only applicable for certain Derived and not all yet this is a base class implementation and must form a contract which is applicable to all.
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.
Fixed
|
||
namespace detail { | ||
template <class T> | ||
concept ExcludedIntegral = is_any_of_v<T, char8_t, char16_t, char32_t, wchar_t>; |
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.
Why must these be excluded?
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.
I've excluded them because they are also excluded for std::ostream -- and so for consistency I did the same.
SDB-8506
|
||
template <class DerivedT> | ||
template <class T> requires std::floating_point<T> | ||
DerivedT& OStreamBase<DerivedT>::put_num(T val) noexcept |
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.
Having these functions declared out of the class was quite jarring for me. Could just be that I'm not used to it, but definitely had to think twice about it.
What do other readers think about it? Is it worth it to get the clean class declaration?
SDB-8506
EDIT: Have run Log.bm.cpp and Net.bm.cpp benchmarks
Improvements ranging from 10% to 252%
BEFORE:
AFTER: