-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
minor perf: update filter state method to reduce repeated hash searching #19609
minor perf: update filter state method to reduce repeated hash searching #19609
Conversation
Signed-off-by: wbpcode <[email protected]>
Signed-off-by: wbpcode <[email protected]>
Signed-off-by: wbpcode <[email protected]>
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 perf fix. A couple of API questions, thank you.
/wait
* An exception will be thrown if the data is not mutable. | ||
*/ | ||
virtual Object* getDataMutableGeneric(absl::string_view data_name) PURE; | ||
|
||
/** | ||
* @param data_name the name of the data being probed. | ||
* @return Whether data of the type and name specified exists in the | ||
* data store. | ||
*/ | ||
template <typename T> bool hasData(absl::string_view data_name) const { |
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.
Is this still used anywhere? Can it be removed to avoid using the pattern you removed in this PR?
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, it is still used when we try to set some value to the filter state.
if(!filter_state.hasData<Type>(name)) {
filter_state.setData(...);
}
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.
Seems like this will also have the same double hash lookup issue? Maybe setData() should have a parameter about whether to set of it already exists? WDYT?
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.
get it.
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.
It looks like it's more complicated than I thought it would be. The parent filter state and the mutable flag make it's hard to change the current hasData then setData
code pattern.
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.
@htuch Sounds reasonable to reserve two different API (getReadOnly
/getMutable
). But I am not sure if we should add special flag(StateType
) for every filter state object.
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 feel less strongly about the state type aspect. It seems like it could catch some kinds of errors, which all things being equal is a good thing. If there really is a genuine performance issue, we can probably eliminate, but I'd vote note to change it unless this is the cause of the observable performance loss.
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.
@htuch StateType
do not result in observable performance loss. But it makes the implementation of FilterState
complex and there are some unsafe scenarios.
The following code is a common use of FilterState
:
if(filter_state.hasData<Type>(name)) {
auto state = filter_state.getDataMutable<Type>(...);
// ......
}
But hasData
will return true
if there is a read only filter state object. Then the getDataMutable
may throws un-catched exception.
However, the StateType can be used to avoid the FilterState Object being overwritten or modified. 🤔 So, there are both advantages and disadvantages.
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.
The example you give is interesting. I think we should have a pattern such as getDataMutableOrNull
and then use that instead of hasData
; that seems the real unsafe thing. I'm not going to strongly advocate for this but I do see some advantage and fixing the above pattern in any case seems desirable.
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.
Sounds great. I will try to solve it in a new PR. 🤔
@mattklein123 @htuch Thanks for all your comments. Sorry for the delayed replies. I have just finished my long holiday. |
Signed-off-by: wbpcode <[email protected]>
…r_state_minor_update
Signed-off-by: wbpcode <[email protected]>
Can you check CI and I will take a look? /wait |
Signed-off-by: wbpcode <[email protected]>
…r_state_minor_update
Signed-off-by: wbpcode <[email protected]>
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 this LGTM with small comments.
/wait
envoy/stream_info/filter_state.h
Outdated
return *result; | ||
template <typename T> const T* getDataReadOnly(absl::string_view data_name) const { | ||
const auto* generic_result = getDataReadOnlyGeneric(data_name); | ||
return generic_result == nullptr ? nullptr : dynamic_cast<const T*>(generic_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.
nit I think you can remove the conditional here and collapse this into a single line. dynamic_cast on nullptr is safe so you can just return that directly. Same below.
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.
get it.
return std::string(); | ||
} | ||
|
||
auto typed_state = dynamic_cast<const StringAccessor*>(state); |
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.
Per other comment dynamic_cast on nullptr is OK so you can collapse this and make it simpler. Same elsewhere.
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.
get it.
Signed-off-by: wbpcode <[email protected]>
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!
…ing (envoyproxy#19609) Signed-off-by: wbpcode <[email protected]> Signed-off-by: Josh Perry <[email protected]>
Commit Message: minor perf: update filter state method to reduce repeated hash searching
Additional Description:
Minor optimization by simple code update. The
fromFilterState
will searchFilterState
multiple times. Some of these searches are duplicates. Try to reduce some unnecessary overhead by simplifying the api.Before:
After:
Risk Level: Low.
Testing: N/A.
Docs Changes: N/A.
Release Notes: N/A.
Platform Specific Features: N/A.