-
Notifications
You must be signed in to change notification settings - Fork 1.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
ProgramMemory: only copy mValues
on write
#6646
Conversation
Some unit tests (e.g. There may also be unnecessary copies introduced by my changes related to |
lib/programmemory.cpp
Outdated
copyOnWrite(); | ||
pm.copyOnWrite(); | ||
|
||
mValues->swap(*pm.mValues); |
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.
Should be mValues.swap(pm.mValues)
.
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.
Done.
lib/programmemory.cpp
Outdated
|
||
void ProgramMemory::copyOnWrite() | ||
{ | ||
if (!mCopyValues) |
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.
There is no need for the mCopyValues
variable. Just check mValues.use_count() == 1
instead.
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.
Will do.
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.
Done.
lib/programmemory.h
Outdated
mValues = other.mValues; | ||
mCopyValues = true; | ||
return *this; | ||
} |
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.
Just use the default-generated copy constructor and assignment.
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.
Without the need for mCopyValues
I can do taht now.
It would have also required the move constructor/assignment.
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.
Done.
lib/valueflow.cpp
Outdated
@@ -896,7 +896,7 @@ struct ValueFlowAnalyzer : Analyzer { | |||
|
|||
using ProgramState = ProgramMemory::Map; | |||
|
|||
virtual ProgramState getProgramState() const = 0; | |||
virtual std::shared_ptr<ProgramState> getProgramState() const = 0; |
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 is this changed to a shared_ptr
? Its never shared.
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.
Because it is used to construct a ProgramMemory
object in ValueFlowAnalyzer::evaluateInt()
.
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.
But you can just move it instead.
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.
Reverted.
mValues
[skip ci]mValues
With the first round of review comments addressed the unit tests now all pass. Here some preliminary numbers (without having looked at the profiling data if everything is on the up and up).
Clang 17 The example from https://trac.cppcheck.net/ticket/10765#comment:4: Clang 17 |
lib/programmemory.h
Outdated
|
||
explicit ProgramMemory(Map values) : mValues(std::move(values)) {} | ||
explicit ProgramMemory(std::shared_ptr<Map> values) : mValues(std::move(values)) {} |
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 should not need to be changed to a shared_ptr
, you can implement it as:
explicit ProgramMemory(Map values) : mValues(new Map()) {
*mValues = std::move(values);
}
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.
Done. Did it even simpler by moving it into the constructor.
@@ -134,19 +134,19 @@ struct ProgramMemory { | |||
void insert(const ProgramMemory &pm); | |||
|
|||
Map::iterator begin() { | |||
return mValues.begin(); | |||
return mValues->begin(); |
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.
lacks copyOnWrite()
as it returns something mutable.
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.
Done.
} | ||
|
||
Map::iterator end() { | ||
return mValues.end(); | ||
return mValues->end(); |
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.
lacks copyOnWrite()
as it returns something mutable.
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.
Done.
6704722
to
25ec10a
Compare
I added some more early outs (might split those into a separate commit later) and removed some unused code. |
30284cc
to
4454389
Compare
mValues
mValues
on write
Unfortunately this does not seem to help much with the selfcheck. ☹ |
Co-authored-by: Paul Fultz II <[email protected]>
…ang-tidy warning
// TODO: how to delay until we actuallly modify? | ||
copyOnWrite(); | ||
|
||
for (auto it = mValues->begin(); it != mValues->end();) { |
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.
Can't this be written as remove-erase?
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.
Possibly but that would not fix the TODO and just clean up the code.
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.
If the call to remove_if()
returns end()
, no modification takes place, or am I missing something?
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.
But we would have to determine if a modification happens, then make the copy and afterwards iterate it again because the existing result is based on a different container.
We only need to make this optimization if it is a hot spot.
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.
remove_if
wouldn't work here anyway: https://stackoverflow.com/questions/9210014/remove-elements-from-an-unordered-map-fulfilling-a-predicate
|
||
explicit ProgramMemory(Map values) : mValues(std::move(values)) {} | ||
explicit ProgramMemory(Map values) : mValues(new Map(std::move(values))) {} |
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.
make_shared
?
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.
That would construct a shared_ptr
object with an shared_ptr
which is unnecessary.
No description provided.