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
10x performance increase; remove uneeded deepcopy field #13673
Conversation
Excellent work. |
The general technique here seems sound. I don't think that _results should
be changed inside of callbacks and the immediate overwrite seems to make
that moot anyhow. I'd want @jimi-c to take a look at this, though. We
started 2.0 removing a lot of deepcopy'ing and then found that it was
needed for one odd reason or another. Jimi-c fixed those so he'd be the
one to recall if there was a reason this is this way.
The implementation has some flaws. Instead of the exclude parameter being
either a list or string we should always take a list-like object. We don't
want to use a list as the default value as it's a mutable type. tuple()
might be a better default. I agree that changing _copy_result() to take
the extra parameter might be the best place to implement this as well.
|
If we merge it into _copy_results, when exclude is not given we can avoid doing the shallow copy as well. That's probably quicker for that case. |
Note: if we keep _copy_result() as just a wrapper around deepcopy, I think we can still shave a small amount of time off by doing it this way:
function calls are expensive in python. Setting _copy_result = deepcopy means that we get rid of the extra intermediate function call. If this is code that gets called frequently (not sure how much is just due to this being a microbenchmark with a loop of 1000x and how much it applies to real-world playbooks) then eliminating the extra call could be valuable. |
|
* _copy_results = deepcopy for better performance * _copy_results_exclude to deepcopy but exclude certain fields. Pop fields that do not need to be deep copied. Re-assign popped fields after deep copy so we don't modify the original, to be copied, object. * _copy_results_exclude unit tests
cf1c293
to
66a8f7e
Compare
Merged into devel as squashed commit 2d11cfa. |
Hmm, that "feels" slow. Let's take a deeper look as to why.
Note: replace
qcachegrind
withkcachegrind
if on Linux.deepcopy
is costly. What is calling it and what can we do about it?lib/ansible/plugins/callback/__init__.py _process_items()
is costly._copy_result()
is basically a wrapper fordeepcopy()
. The copy ofresult._result
is being overwritten innewres._result = res
. What happens if we don't deep copy_result
?Wowzers!
=~ 10x speedup
Implementation Thoughts
Instead of creating a
deepcopy_exclude()
method, instead modify_copy_result()
to accept theexclude
parameter. If exclude parameter included in the call then behave likedeepcopy_exclude()