Skip to content
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

Improve time complexity of removal of callback handle. #11751

Merged
merged 38 commits into from
Jul 7, 2020
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
959fd1f
api: rename num_retries to max_retries (#11729)
numerodix Jun 24, 2020
41e092a
test: Split huge monolith mock header to speed up test compilation (#…
foreseeable Jun 25, 2020
3eb115b
build: removing hard-coded extension from generate_extension_db.py (…
alyssawilk Jun 25, 2020
1bc6ad1
Windows: test compilation refresh (#11719)
sunjayBhatia Jun 25, 2020
e80b2a5
Signed-off-by: chaoqinli <chaoqinli@google.com>
Jun 24, 2020
dc16f65
make cast dynamic
Jun 25, 2020
e95fc7c
Signed-off-by: chaoqinli <chaoqinli@google.com>
Jun 24, 2020
89fc19f
make cast dynamic
Jun 25, 2020
2c9a3b8
examples: fixed fault-injection delay demo (#11715)
cpakulski Jun 25, 2020
b03decc
Merge branch 'master' of https://github.com/envoyproxy/envoy into con…
Jun 25, 2020
eb5ed70
format
Jun 25, 2020
1f211a3
format
Jun 25, 2020
a2e7ffd
format
Jun 25, 2020
72cc8ac
Merge branch 'master' of https://github.com/envoyproxy/envoy into con…
Jun 25, 2020
d0354cb
Merge branch 'master' of https://github.com/envoyproxy/envoy into con…
Jun 26, 2020
2d9a9fa
rollback sth
Jun 26, 2020
4c97b8d
rollback sth
Jun 26, 2020
956b32a
Merge branch 'master' of https://github.com/envoyproxy/envoy into con…
Jun 26, 2020
4f1bd5f
rollback sth
Jun 26, 2020
d859a2f
rollback sth
Jun 26, 2020
5739de5
rollback sth
Jun 26, 2020
7c4bf5a
rollback sth
Jun 26, 2020
e089eb8
Merge branch 'master' of https://github.com/envoyproxy/envoy into con…
Jun 27, 2020
6dc2de4
rollback sth
Jun 27, 2020
3e5ceaa
rollback sth
Jun 27, 2020
ccd18e6
increase memory upper bound
Jun 27, 2020
0d0a7d6
increase exact memory consumed
Jun 27, 2020
26de9e3
Merge branch 'master' of https://github.com/envoyproxy/envoy into con…
Jun 29, 2020
d75466a
add comment of stats memory test
Jun 29, 2020
a850f6d
add comments, remove unrelated fixups
Jun 30, 2020
e8afadd
Merge branch 'master' of https://github.com/envoyproxy/envoy into con…
Jun 30, 2020
e227506
add comments, remove unrelated fixups
Jun 30, 2020
7c62189
fix format
Jun 30, 2020
d11b19a
fix format
Jun 30, 2020
b1ba481
Merge branch 'master' of https://github.com/envoyproxy/envoy into con…
Jul 1, 2020
b2ce936
fix format
Jul 1, 2020
fbc6a7d
Merge branch 'master' of https://github.com/envoyproxy/envoy into con…
Jul 3, 2020
85b84f4
Merge branch 'master' of https://github.com/envoyproxy/envoy into con…
Jul 6, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions source/common/common/callback_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ template <typename... CallbackArgs> class CallbackManager {
*/
CallbackHandle* add(Callback callback) {
callbacks_.emplace_back(*this, callback);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it looks good. can you move this into the constructor? caller doesnt have to modify the handle outside of its box

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure what is going on, I will pull from upstream to retest it first, it the same error show up again, I will test the change to find the bug.

callbacks_.back().it_ = (--callbacks_.end());
return &callbacks_.back();
}

Expand All @@ -46,24 +47,21 @@ template <typename... CallbackArgs> class CallbackManager {
CallbackHolder(CallbackManager& parent, Callback cb) : parent_(parent), cb_(cb) {}

// CallbackHandle
void remove() override { parent_.remove(this); }
void remove() override { parent_.remove(it_); }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, I think the safety of this depends on:

"Adding, removing and moving the elements within the list or across several lists does not invalidate the iterators or references. An iterator is invalidated only when the corresponding element is deleted."

in https://en.cppreference.com/w/cpp/container/list. I.e. that this is a std::list. I'd add some comments to the call sites here and where it_ is initialized, as well as to where callbacks_ is defined, to make sure that this is clear as an invariant.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is guaranteed by C++ standard that list iterator won't be invalidated by list operation.


CallbackManager& parent_;
Callback cb_;

// the iterator of this callback holder inside callbacks_ list
// upon removal, use this iterator to delete callback holder in O(1)
typename std::list<CallbackHolder>::iterator it_;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have you considered to use a hashmap which may make the code a little easier to read?

Copy link
Member Author

@chaoqin-li1123 chaoqin-li1123 Jun 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am worried that a hashmap may incur more memory consumption and performance penalty. Also, storing a list iterator make the code less verbose without all the hashing and searching. As suggested, I have added some comment to make the code more readable.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think what is done here is fine, as it's basically just std::list iterator semantics, which could be explained a bit better but are fairly clear.

};

/**
* Remove a member update callback added via add().
* @param handle supplies the callback handle to remove.
*/
void remove(CallbackHandle* handle) {
ASSERT(std::find_if(callbacks_.begin(), callbacks_.end(),
[handle](const CallbackHolder& holder) -> bool {
return handle == &holder;
}) != callbacks_.end());
callbacks_.remove_if(
[handle](const CallbackHolder& holder) -> bool { return handle == &holder; });
}
void remove(typename std::list<CallbackHolder>::iterator& it) { callbacks_.erase(it); }

std::list<CallbackHolder> callbacks_;
};
Expand Down
4 changes: 1 addition & 3 deletions source/common/router/scoped_rds.cc
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,7 @@ InlineScopedRoutesConfigProvider::InlineScopedRoutesConfigProvider(
ConfigProvider::ApiType::Delta),
name_(std::move(name)),
config_(std::make_shared<ScopedConfigImpl>(std::move(scope_key_builder))),
config_protos_(std::make_move_iterator(config_protos.begin()),
std::make_move_iterator(config_protos.end())),
rds_config_source_(std::move(rds_config_source)) {}
config_protos_(move(config_protos)), rds_config_source_(std::move(rds_config_source)) {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you remove the unrelated optimization fixups and put them in a separate misc: PR?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I agree that these changes should be in another PR.


ScopedRdsConfigSubscription::ScopedRdsConfigSubscription(
const envoy::extensions::filters::network::http_connection_manager::v3::ScopedRds& scoped_rds,
Expand Down
1 change: 1 addition & 0 deletions source/common/router/scoped_rds.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class InlineScopedRoutesConfigProvider : public Envoy::Config::ImmutableConfigPr
// Envoy::Config::ConfigProvider
Envoy::Config::ConfigProvider::ConfigProtoVector getConfigProtos() const override {
Envoy::Config::ConfigProvider::ConfigProtoVector out_protos;
out_protos.reserve(config_protos_.size());
std::for_each(config_protos_.begin(), config_protos_.end(),
[&out_protos](const std::unique_ptr<const Protobuf::Message>& message) {
out_protos.push_back(message.get());
Expand Down
4 changes: 2 additions & 2 deletions test/integration/stats_integration_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ TEST_P(ClusterMemoryTestRunner, MemoryLargeClusterSizeWithFakeSymbolTable) {
// If you encounter a failure here, please see
// https://github.com/envoyproxy/envoy/blob/master/source/docs/stats.md#stats-memory-tests
// for details on how to fix.
EXPECT_MEMORY_EQ(m_per_cluster, 44491);
EXPECT_MEMORY_EQ(m_per_cluster, 44715);
EXPECT_MEMORY_LE(m_per_cluster, 46000); // Round up to allow platform variations.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you update the comment section above and explain a little bit why this bump is necessary?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have updated the comment. If there are a lot of callbacks in a callback manager or if adding and removing callbacks is frequent, making removal of callback handle O(1) will be a good trade off because storing a iterator is lightweight. It will make the memory consumption of a callback holder increase from 48 bytes to 56 bytes in a 64 bit linux system, but will be likely to improve performance when callback is used frequently.

}

Expand Down Expand Up @@ -349,7 +349,7 @@ TEST_P(ClusterMemoryTestRunner, MemoryLargeClusterSizeWithRealSymbolTable) {
// If you encounter a failure here, please see
// https://github.com/envoyproxy/envoy/blob/master/source/docs/stats.md#stats-memory-tests
// for details on how to fix.
EXPECT_MEMORY_EQ(m_per_cluster, 36603);
EXPECT_MEMORY_EQ(m_per_cluster, 36827);
EXPECT_MEMORY_LE(m_per_cluster, 38000); // Round up to allow platform variations.
}

Expand Down