Skip to content

make ClusterInfo::traffic_stats_ a unique_ptr, so that later we can lazy-init it later.#24406

Merged
ggreenway merged 14 commits intoenvoyproxy:mainfrom
stevenzzzz:ClusterTrafficStats_unique_ptr
Dec 14, 2022
Merged

make ClusterInfo::traffic_stats_ a unique_ptr, so that later we can lazy-init it later.#24406
ggreenway merged 14 commits intoenvoyproxy:mainfrom
stevenzzzz:ClusterTrafficStats_unique_ptr

Conversation

@stevenzzzz
Copy link
Copy Markdown
Contributor

@stevenzzzz stevenzzzz commented Dec 7, 2022

Commit Message: make ClusterInfo::traffic_stats_ a unique_ptr, so that later we can lazy-init it later.
Additional Description: Cribbed from #23921, this PR is to split the bulk of "." ==> "->" changes in that PR.

NOTE: in this PR the renaming from ClusterInfoImpl::stats_ --> ClusterInfoImpl::traffic_stats_ is also included, sorry for the extra diffs, but hopefully it's straightforward enough to review.

context issue: #23575

Risk Level: LOW, no behavior change.
Testing: Existing unit test.
Docs Changes:
Release Notes:
Platform Specific Features:
[Optional Runtime guard:]
[Optional Fixes #Issue]
[Optional Fixes commit #PR or SHA]
[Optional Deprecated:]
[Optional API Considerations:]

…azyInit it

Signed-off-by: Xin Zhuang <stevenzzz@google.com>
@repokitteh-read-only
Copy link
Copy Markdown

CC @envoyproxy/api-shepherds: Your approval is needed for changes made to (api/envoy/|docs/root/api-docs/).
envoyproxy/api-shepherds assignee is @lizan
CC @envoyproxy/api-watchers: FYI only for changes made to (api/envoy/|docs/root/api-docs/).

🐱

Caused by: #24406 was opened by stevenzzzz.

see: more, trace.

Signed-off-by: Xin Zhuang <stevenzzz@google.com>
@stevenzzzz
Copy link
Copy Markdown
Contributor Author

hi Josh, PTAL.
/assign @jmarantz

Signed-off-by: Xin Zhuang <stevenzzz@google.com>
Signed-off-by: Xin Zhuang <stevenzzz@google.com>
Signed-off-by: Xin Zhuang <stevenzzz@google.com>
Copy link
Copy Markdown
Contributor

@jmarantz jmarantz left a comment

Choose a reason for hiding this comment

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

OK I'm done with this round.

Let's not use multiple inheritance for the tests. And the other broad thing is to make a type nickname for your unique_ptr.


/**
* @return ClusterTrafficStats& all traffic related stats for this cluster.
* @return std::unique_ptr<ClusterTrafficStats>& all traffic related stats for this cluster.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can you make a nickname ClusterTrafficStatsPtr for the unique_ptr?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Since we're not passing the ownership here, just use raw pointer ClusterTrafficStats* instead of returning a reference to unique ptr?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is a good point, Lizan. However that will not be convenient for the follow-up for this PR.

That's because we want to (once we sort out some semantic issues around stat continuity) return a LazyInit& here.

I had suggested making this change as an intermediate step because it is a large PR but is (arguably) obviously correct.

Then when we have solved stat continuity across xds updates we would be able to pass around the lazy-init reference, and then the first time a stat is incremented, we'll instantiate the block of stats.

I think this might appear more palatable once Xin adds a nickname for this.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sounds good, if this is an intermediate state just add some comment explaining. A nickname helps as well.

host_->cluster().trafficStats().upstream_rq_total_.inc();
host_->cluster().trafficStats().upstream_rq_active_.inc();
host_->cluster().trafficStats()->upstream_rq_total_.inc();
host_->cluster().trafficStats()->upstream_rq_active_.inc();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

capture *host_->cluster().trafficStats() in a temp.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

: parent_(parent), can_send_early_data_(can_send_early_data) {
parent_.host()->cluster().trafficStats().upstream_rq_pending_total_.inc();
parent_.host()->cluster().trafficStats().upstream_rq_pending_active_.inc();
parent_.host()->cluster().trafficStats()->upstream_rq_pending_total_.inc();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

capture *host_->cluster().trafficStats() in a temp.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

parent_.host()->cluster().trafficStats().upstream_cx_total_.inc();
parent_.host()->cluster().trafficStats().upstream_cx_active_.inc();
parent_.host()->cluster().trafficStats()->upstream_cx_total_.inc();
parent_.host()->cluster().trafficStats()->upstream_cx_active_.inc();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

capture *host_->cluster().trafficStats() in a temp.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

time_source_(dispatcher.timeSource()), redis_command_stats_(redis_command_stats),
scope_(scope), is_transaction_client_(is_transaction_client) {
host->cluster().trafficStats().upstream_cx_total_.inc();
host->cluster().trafficStats()->upstream_cx_total_.inc();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

capture *host_->cluster().trafficStats() in a temp.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

};

class LookupWithStatNameTest : public ThreadLocalStoreNoMocksTestBase {};
class LookupWithStatNameTest : public ThreadLocalStoreNoMocksTestBase, public testing::Test {};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Instead of multiple inheritance, please make ThreadLocalStoreNoMocksTestBase derive from testing::Test.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

this is to be reused later in a BENCHMARK test, the testing class there inherits from not necessarily is a testing::Test.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Use composition rather than multiple inheritance for that pattern.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

if not feeling strongly, I'd hope it stay this way. I am not sure how much the composition pattern would help with readability here. OTOH, the original ThreadLocalRealThreadsTestBase is already a multiple inheritance impl.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actually I agree with you - this is consistent with other test helper classes in Envoy.

One thing that's a little concerning is that usually the needs of performance tests are not consistent from the needs of unit tests, so they may not want to share that much code, but in this case I think it is helpful to do the sharing.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ACK.

@jmarantz
Copy link
Copy Markdown
Contributor

jmarantz commented Dec 7, 2022

/wait

Signed-off-by: Xin Zhuang <stevenzzz@google.com>
Copy link
Copy Markdown
Contributor Author

@stevenzzzz stevenzzzz left a comment

Choose a reason for hiding this comment

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

Thanks, PTAL.

};

class LookupWithStatNameTest : public ThreadLocalStoreNoMocksTestBase {};
class LookupWithStatNameTest : public ThreadLocalStoreNoMocksTestBase, public testing::Test {};
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

this is to be reused later in a BENCHMARK test, the testing class there inherits from not necessarily is a testing::Test.

time_source_(dispatcher.timeSource()), redis_command_stats_(redis_command_stats),
scope_(scope), is_transaction_client_(is_transaction_client) {
host->cluster().trafficStats().upstream_cx_total_.inc();
host->cluster().trafficStats()->upstream_cx_total_.inc();
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

host_->cluster().trafficStats().upstream_rq_total_.inc();
host_->cluster().trafficStats().upstream_rq_active_.inc();
host_->cluster().trafficStats()->upstream_rq_total_.inc();
host_->cluster().trafficStats()->upstream_rq_active_.inc();
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done


/**
* @return ClusterTrafficStats& all traffic related stats for this cluster.
* @return std::unique_ptr<ClusterTrafficStats>& all traffic related stats for this cluster.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

: parent_(parent), can_send_early_data_(can_send_early_data) {
parent_.host()->cluster().trafficStats().upstream_rq_pending_total_.inc();
parent_.host()->cluster().trafficStats().upstream_rq_pending_active_.inc();
parent_.host()->cluster().trafficStats()->upstream_rq_pending_total_.inc();
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

parent_.host()->cluster().trafficStats().upstream_cx_total_.inc();
parent_.host()->cluster().trafficStats().upstream_cx_active_.inc();
parent_.host()->cluster().trafficStats()->upstream_cx_total_.inc();
parent_.host()->cluster().trafficStats()->upstream_cx_active_.inc();
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

Copy link
Copy Markdown
Contributor

@jmarantz jmarantz left a comment

Choose a reason for hiding this comment

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

/wait

Signed-off-by: Xin Zhuang <stevenzzz@google.com>
};

class LookupWithStatNameTest : public ThreadLocalStoreNoMocksTestBase {};
class LookupWithStatNameTest : public ThreadLocalStoreNoMocksTestBase, public testing::Test {};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actually I agree with you - this is consistent with other test helper classes in Envoy.

One thing that's a little concerning is that usually the needs of performance tests are not consistent from the needs of unit tests, so they may not want to share that much code, but in this case I think it is helpful to do the sharing.

}
};

for (const Stats::CounterSharedPtr& counter : test_server_->counters()) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

revert this file?

@jmarantz
Copy link
Copy Markdown
Contributor

jmarantz commented Dec 9, 2022

/wait

Signed-off-by: Xin Zhuang <stevenzzz@google.com>
@jmarantz
Copy link
Copy Markdown
Contributor

jmarantz commented Dec 9, 2022

/wait

Signed-off-by: Xin Zhuang <stevenzzz@google.com>
Copy link
Copy Markdown
Contributor Author

@stevenzzzz stevenzzzz left a comment

Choose a reason for hiding this comment

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

Thanks

Signed-off-by: Xin Zhuang <stevenzzz@google.com>
@stevenzzzz
Copy link
Copy Markdown
Contributor Author

stevenzzzz commented Dec 12, 2022 via email

jmarantz
jmarantz previously approved these changes Dec 13, 2022
Copy link
Copy Markdown
Contributor

@jmarantz jmarantz left a comment

Choose a reason for hiding this comment

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

lgtm with small nits

EXPECT_EQ(5, factory_context_.cluster_manager_.thread_local_cluster_.cluster_.info_->stats_
.upstream_cx_tx_bytes_total_.value());
EXPECT_EQ(5, factory_context_.cluster_manager_.thread_local_cluster_.cluster_.info_
->traffic_stats_->upstream_cx_tx_bytes_total_.value());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm surprised to see this particular diff; I thought you already partitioned the stat into separate blocks in a previous PR.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

the renaming? it's not included in the previous PRs.

Signed-off-by: Xin Zhuang <stevenzzz@google.com>
Signed-off-by: Xin Zhuang <stevenzzz@google.com>
Signed-off-by: Xin Zhuang <stevenzzz@google.com>
Signed-off-by: Xin Zhuang <stevenzzz@google.com>
Copy link
Copy Markdown
Contributor

@jmarantz jmarantz left a comment

Choose a reason for hiding this comment

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

Thanks -- this looks great!

// For example, we also want to record the stats in the case of BiDi streaming APIs where we
// might have already seen the headers.
cluster_->trafficStats().upstream_rq_timeout_.inc();
cluster_->trafficStats()->upstream_rq_timeout_.inc();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

just want to point out that this whole lazy optimization change has a lot of sense from the perspective of the mobile Envoy (that runs on iOS and Android devices) too.

For the mobile applications a lot of impact could be realized if we added lazy initiation to virtual cluster stats. They are managed in multiple places but one of them is just a line below the line I commented on. Are there any plans to make the initialization of virtual cluster stats lazy too or is this outside of the scope of work/changes that you are work on?

Copy link
Copy Markdown
Member

@ggreenway ggreenway left a comment

Choose a reason for hiding this comment

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

LGTM

@ggreenway ggreenway merged commit 7d9805b into envoyproxy:main Dec 14, 2022
jpsim added a commit that referenced this pull request Dec 14, 2022
…-tools

* origin/main: (59 commits)
  Make IsOkAndHolds matcher work with submatchers (#24498)
  ios: fix platform key value store (#24532)
  make ClusterInfo::traffic_stats_ a unique_ptr, so that later we can lazy-init it later. (#24406)
  quic: splitting into client and server (#24513)
  fixing coverage (#24529)
  ci: Add `examplesOnly` condition (#24465)
  ci: sonatype_nexus_upload.py: remove unused format argument (#24471)
  deps: Bump `build_bazel_rules_apple` -> 1.1.3 (#24527)
  deps: Bump `com_github_nghttp2_nghttp2` -> 1.51.0 (#24525)
  deps: Bump `rules_license` -> 0.0.4 (#24523)
  build(deps): bump sphinxcontrib-httpdomain from 1.8.0 to 1.8.1 in /mobile/docs (#24126)
  build(deps): bump github/codeql-action from 2.1.35 to 2.1.36 (#24473)
  build(deps): bump openpolicyagent/opa from 0.47.2-istio to 0.47.3-istio in /examples/ext_authz (#24514)
  build(deps): bump node from `80844b6` to `2770c78` in /examples/ext_authz/auth/http-service (#24515)
  build(deps): bump abseil-cpp to latest version (#24386)
  xDS: add xDS config tracker extension point (#23485)
  kafka: add shared consumer manager (#24494)
  coverage: Improve test coverage (#24355)
  deps: Bump `rules_python` -> 0.16.1 (#24344)
  ci: revert disable running the Objective-C integration app (#24478)" (#24496)
  ...

Signed-off-by: JP Simard <jp@jpsim.com>
JuniorHsu pushed a commit to JuniorHsu/envoy that referenced this pull request Dec 15, 2022
Signed-off-by: kuochunghsu <kuochunghsu@pinterest.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants