Skip to content

server: Refactor stream observer #95

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

Merged
merged 14 commits into from
Jul 25, 2019

Conversation

sschepens
Copy link
Contributor

The objective of this PR is to reduce the complexity and overhead when not operating in ADS mode.
When working with separate XDS streams the StreamObserver logic can be much simpler and it does not need to store maps, thus reducing the memory overhead.
This also includes a change in Watch and StreamObserver to use Atomic*FieldUpdaters instead of Atomic* which reduces the memory overhead per instance.

I realize this introduces a bit of indirection and probably code complexity, but this should be a win when not operating in ADS mode and having thousands of streams.

Copy link
Contributor

@jakubdyszkiewicz jakubdyszkiewicz left a comment

Choose a reason for hiding this comment

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

Nice! Do you have any numbers how much did it improve performance of your control plane?

}
} else if (requestTypeUrl.isEmpty()) {
requestTypeUrl = defaultTypeUrl;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you can simplify it. For the defaultTypeUrl you always pass ANY_TYPE_URL. You can delete the defaultTypeUrl from the constructor, pass the ANY_TYPE_URL to DiscoveryRequestStreamObserver.
Then you can delete if (defaultTypeUrl.equals(ANY_TYPE_URL)) { if and also } else if (requestTypeUrl.isEmpty()) { branch

Copy link
Contributor Author

Choose a reason for hiding this comment

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

that is correct, good catch 👍

@sschepens
Copy link
Contributor Author

Haven't run any masurements yet, will do.
I don't know if the perf improvements will be very noticeable, but the memory savings should be considerable. We currently have 3 ConcurrentHashMaps per stream a quick inspection reveals that it has a lot of fields and surely has a lot of memory overhead vs 3 simple reference fields.
Atomic field updaters should also give some considerable amount of savings.

Gonna run some measurements to see exactly how much memory we would be saving.

@codecov-io
Copy link

codecov-io commented Mar 13, 2019

Codecov Report

Merging #95 into master will decrease coverage by 0.3%.
The diff coverage is 90.9%.

Impacted file tree graph

@@             Coverage Diff             @@
##             master     #95      +/-   ##
===========================================
- Coverage      89.8%   89.5%   -0.31%     
- Complexity      149     193      +44     
===========================================
  Files            19      22       +3     
  Lines           569     600      +31     
  Branches         53      48       -5     
===========================================
+ Hits            511     537      +26     
- Misses           44      48       +4     
- Partials         14      15       +1
Impacted Files Coverage Δ Complexity Δ
...nvoyproxy/controlplane/server/DiscoveryServer.java 100% <100%> (+5.18%) 15 <0> (+1) ⬆️
...lane/server/XdsDiscoveryRequestStreamObserver.java 100% <100%> (ø) 9 <9> (?)
...n/java/io/envoyproxy/controlplane/cache/Watch.java 100% <100%> (ø) 12 <7> (+2) ⬆️
...lane/server/AdsDiscoveryRequestStreamObserver.java 100% <100%> (ø) 12 <12> (?)
...olplane/server/DiscoveryRequestStreamObserver.java 85.36% <85.36%> (ø) 20 <20> (?)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update f127e26...5f91376. Read the comment docs.

@sschepens
Copy link
Contributor Author

sschepens commented Mar 13, 2019

So, I ran some measurements creating 1M objects of Watch and DiscoveryRequestStreamObserver, here are the results.

Before

  • Watch: 20 bytes for AtomicBoolean + 49 bytes for Watch object itself. `Totalling: 69 bytes per Watch
  • DiscoveryRequestStreamObserver: 24 bytes for AtomicLong + 100 bytes for ConcurrentHashMap * 3 maps per observer + 89 bytes for DiscoveryRequestStreamObserver object itself. Totalling: 413 bytes per DiscoveryRequestStreamObserver

After:

  • Watch: 45 bytes for WatchObject itself (no other object is created except for static atomic field updater). Totalling: 45 bytes per Watch
  • AdsDiscoveryRequestStreamObserver: 100 bytes for ConcurrentHashMap * 3 maps per observer + 88 bytes for AdsDiscoveryRequestStreamObserver object itself. Totalling: 388 bytes per AdsDiscoveryRequestStreamObserver
  • XdsDiscoveryRequestStreamObserver: 88 bytes for XdsDiscoveryRequestStreamObserver object itself. Totalling: 88 bytes per XdsDiscoveryRequestStreamObserver

Conclusions:

  • Watch: we end up saving 24 bytes (about 34%) per each Watch created.
  • AdsDiscoveryRequestStreamObserver: we end up saving 25 bytes (about 6%) per each AdsDiscoveryRequestStreamObserver.
  • XdsDiscoveryRequestStreamObserver: we end up saving 325 bytes (about 78%) for each XdsDiscoveryRequestStreamObserver.

The savings are noticeable enough for Watches and are incredible when operating with separate XDS streams.

Of course there should also be performance improvements when operating with separate XDS streams coming from not using concurrent hash maps but plain field access.

Attaching results:
Annotation 2019-03-12 233812
Annotation 2019-03-12 232452
Annotation 2019-03-12 232823
Annotation 2019-03-12 232946
Annotation 2019-03-12 233136

Copy link
Contributor

@jakubdyszkiewicz jakubdyszkiewicz left a comment

Choose a reason for hiding this comment

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

LGTM, thanks for the report on the performance improvements!

@snowp
Copy link
Contributor

snowp commented Mar 18, 2019

@joeyb Mind taking a look at this? I'm having a hard time finding time to review this unfortunately

@sschepens
Copy link
Contributor Author

@snowp @joeyb can any of you please review this?

Copy link
Contributor

@snowp snowp left a comment

Choose a reason for hiding this comment

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

This makes sense, thanks.

@jakubdyszkiewicz
Copy link
Contributor

@sschepens can I ask whether you planning to work on this PR? I think that the improvements are valuable and it would be great to have this merged.

@sschepens
Copy link
Contributor Author

@jakubdyszkiewicz yeah, wanted to follow up on this, i had the relevant changes made, but then i got my laptop replaced because of hardware issues and lost them.

I'll see if i can address the comments today

- Extract from Discovery server
- Create abstract class
- Create Ads observer which maintains current structure
- Create simpler Xds observer with less overhead

Signed-off-by: sschepens <[email protected]>
Signed-off-by: Sebastian Schepens <[email protected]>
Signed-off-by: sschepens <[email protected]>
Signed-off-by: Sebastian Schepens <[email protected]>
Signed-off-by: sschepens <[email protected]>
Signed-off-by: Sebastian Schepens <[email protected]>
Signed-off-by: sschepens <[email protected]>
Signed-off-by: Sebastian Schepens <[email protected]>
Signed-off-by: sschepens <[email protected]>
Signed-off-by: Sebastian Schepens <[email protected]>
Signed-off-by: sschepens <[email protected]>
Signed-off-by: Sebastian Schepens <[email protected]>
@sschepens sschepens force-pushed the refactor-stream-observer branch from dbaa3f8 to 386a529 Compare July 12, 2019 17:33
Signed-off-by: Sebastian Schepens <[email protected]>
@sschepens
Copy link
Contributor Author

@snowp @jakubdyszkiewicz addressed comments, review?

Copy link
Contributor

@jakubdyszkiewicz jakubdyszkiewicz left a comment

Choose a reason for hiding this comment

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

Can you rebase to current master?

@sschepens sschepens force-pushed the refactor-stream-observer branch from 495215f to 214ddca Compare July 19, 2019 14:23
@sschepens
Copy link
Contributor Author

@jakubdyszkiewicz updated from master

Signed-off-by: Sebastian Schepens <[email protected]>
@sschepens sschepens force-pushed the refactor-stream-observer branch from 827352f to 94dfbac Compare July 19, 2019 15:16
Signed-off-by: Sebastian Schepens <[email protected]>
Signed-off-by: Sebastian Schepens <[email protected]>
@sschepens sschepens force-pushed the refactor-stream-observer branch from c70d576 to b81ef44 Compare July 19, 2019 16:31
Signed-off-by: Sebastian Schepens <[email protected]>
@jakubdyszkiewicz
Copy link
Contributor

@snowp can you look at it? Merging is blocked by "change requested"

snowp
snowp previously approved these changes Jul 25, 2019
Copy link
Contributor

@snowp snowp left a comment

Choose a reason for hiding this comment

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

Just a tiny nit, otherwise LGTM. Thanks for the contribution! Approving so I won't block merging

@sschepens sschepens dismissed stale reviews from snowp and jakubdyszkiewicz via e2c8c54 July 25, 2019 18:18
Signed-off-by: Sebastian Schepens <[email protected]>
@sschepens sschepens force-pushed the refactor-stream-observer branch from e2c8c54 to 5f91376 Compare July 25, 2019 18:19
@sschepens
Copy link
Contributor Author

@jakubdyszkiewicz @snowp addressed last comment

@jakubdyszkiewicz
Copy link
Contributor

Thank you! Great job

@sschepens
Copy link
Contributor Author

@snowp could we get a release including the latest changes?

@jakubdyszkiewicz
Copy link
Contributor

@snowp we would like to know what's is the instruction for releasing a new version. Is there a link to it? If not, can you drop me the message at my mail (github profile) or Envoy Slack?
@sschepens it seems that there are still some conflicts.

@joeyb
Copy link
Contributor

joeyb commented Jul 25, 2019

@jakubdyszkiewicz - I haven't written any formal docs yet, but I'll send you the release instructions on slack.

@sschepens
Copy link
Contributor Author

@sschepens it seems that there are still some conflicts.

@jakubdyszkiewicz conflicts which prevent merging this? github isn't reporting any conflicts to me

@jakubdyszkiewicz
Copy link
Contributor

It does for me

image

@sschepens
Copy link
Contributor Author

may be try a Squash and Merge instead?

@jakubdyszkiewicz jakubdyszkiewicz merged commit b08db6a into envoyproxy:master Jul 25, 2019
@sschepens sschepens deleted the refactor-stream-observer branch July 25, 2019 18:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants