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

MSQ: Add CPU and thread usage counters. #16914

Merged
merged 4 commits into from
Aug 31, 2024
Merged

Conversation

gianm
Copy link
Contributor

@gianm gianm commented Aug 16, 2024

The main change adds "cpu" and "wall" counters. The "cpu" counter measures CPU time (using JvmUtils.getCurrentThreadCpuTime) taken up by processors in processing threads. The "wall" counter measures the amount of wall time taken up by processors in those same processing threads. Both counters are broken down by type of processor.

This patch also includes changes to support adding new counters. Due to an oversight in the original design, older deserializers are not forwards-compatible; they throw errors when encountering an unknown counter type. To manage this, the following changes are made:

  1. The defaultImpl NilQueryCounterSnapshot is added to QueryCounterSnapshot's deserialization configuration. This means that any unrecognized counter types will be read as nil by deserializers. Going forward, once all servers are on the latest code, this is enough to enable easily adding new counters.

  2. A new context parameter includeAllCounters is added, which defaults to "false". When this parameter is set false, only legacy counters are included. When set to true, all counters are included. This is currently undocumented. In a future version, we should set the default to true, and at that time, include a release note that people updating from versions prior to Druid 31 should set this to false until their upgrade is complete.

The main change adds "cpu" and "wall" counters. The "cpu" counter measures
CPU time (using JvmUtils.getCurrentThreadCpuTime) taken up by processors
in processing threads. The "wall" counter measures the amount of wall time
taken up by processors in those same processing threads. Both counters are
broken down by type of processor.

This patch also includes changes to support adding new counters. Due to an
oversight in the original design, older deserializers are not forwards-compatible;
they throw errors when encountering an unknown counter type. To manage this,
the following changes are made:

1) The defaultImpl NilQueryCounterSnapshot is added to QueryCounterSnapshot's
   deserialization configuration. This means that any unrecognized counter types
   will be read as "nil" by deserializers. Going forward, once all servers are
   on the latest code, this is enough to enable easily adding new counters.

2) A new context parameter "includeAllCounters" is added, which defaults to "false".
   When this parameter is set "false", only legacy counters are included. When set
   to "true", all counters are included. This is currently undocumented. In a future
   version, we should set the default to "true", and at that time, include a release
   note that people updating from versions prior to Druid 31 should set this to
   "false" until their upgrade is complete.
@gianm gianm added this to the 31.0.0 milestone Aug 16, 2024
@github-actions github-actions bot added Area - Batch Ingestion Area - MSQ For multi stage queries - https://github.com/apache/druid/issues/12262 labels Aug 16, 2024
@LakshSingla
Copy link
Contributor

@kgyrtkirk was evaluating the performance implications of measuring the cpuTime too frequently. He has documented a flame graph #16859 wherein the call to .yield() was being made per row, which causes getCurrentThreadCpuTime to be called per row.
runIncrementally also runs on a similar contract, and since each runIncrementally call entails two getCurrentThreadCpuTime calls, should we consider/measure the perf impact of the change?

@gianm
Copy link
Contributor Author

gianm commented Aug 21, 2024

runIncrementally when well-written should be generating one full output frame, meaning the measurement overhead is amortized over many rows. So I don't think it would be as bad as the case from #16859. I can still measure it though.

@LakshSingla
Copy link
Contributor

A new context parameter includeAllCounters is added, which defaults to "false". When this parameter is set false, only legacy counters are included. When set to true, all counters are included. This is currently undocumented. In a future version, we should set the default to true, and at that time, include a release note that people updating from versions prior to Druid 31 should set this to false until their upgrade is complete.

@gianm WDYT about leaving the parameter undocumented, and being set by the broker. This takes advantage of the fact that brokers are upgraded last and if set by the broker, Druid can assume that all the workers are on a newer version. This will remove the user intervention.

@LakshSingla
Copy link
Contributor

runIncrementally when well-written should be generating one full output frame, meaning the measurement overhead is amortized over many rows. So I don't think it would be as bad as the case from #16859. I can still measure it though.

Thanks for confirming. I think if it is amortized, it shouldn't be an issue. The flame graph in the attached ticket feels misleading too, since turning off that code path doesn't lead to as much perf increase as anticipated.

@gianm
Copy link
Contributor Author

gianm commented Aug 22, 2024

@gianm WDYT about leaving the parameter undocumented, and being set by the broker. This takes advantage of the fact that brokers are upgraded last and if set by the broker, Druid can assume that all the workers are on a newer version. This will remove the user intervention.

Unfortunately that wouldn't work well with async queries. If one Broker is updated and another isn't, and the user tries to retrieve information from the task report via async query APIs on the non-updated Broker, that non-updated Broker will error out when trying to read the unrecognized counters.

Thanks for confirming. I think if it is amortized, it shouldn't be an issue. The flame graph in the attached ticket feels misleading too, since turning off that code path doesn't lead to as much perf increase as anticipated.

It could be some bias in the profiling. They do have that sometimes.

@gianm
Copy link
Contributor Author

gianm commented Aug 23, 2024

Does that mean we're good to merge this one?

Copy link
Contributor

@LakshSingla LakshSingla left a comment

Choose a reason for hiding this comment

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

I wasn't done with the review when I left the previous comments. Just finished up the review and it seems good to me. Apologies for the delay

@gianm
Copy link
Contributor Author

gianm commented Aug 31, 2024

I wasn't done with the review when I left the previous comments. Just finished up the review and it seems good to me. Apologies for the delay

all good- thanks!

@gianm gianm merged commit caf8ce3 into apache:master Aug 31, 2024
90 checks passed
@gianm gianm deleted the msq-cpu-counters branch August 31, 2024 03:02
gianm added a commit to gianm/druid that referenced this pull request Sep 3, 2024
abhishekrb19 pushed a commit that referenced this pull request Sep 3, 2024
edgar2020 pushed a commit to edgar2020/druid that referenced this pull request Sep 5, 2024
* MSQ: Add CPU and thread usage counters.

The main change adds "cpu" and "wall" counters. The "cpu" counter measures
CPU time (using JvmUtils.getCurrentThreadCpuTime) taken up by processors
in processing threads. The "wall" counter measures the amount of wall time
taken up by processors in those same processing threads. Both counters are
broken down by type of processor.

This patch also includes changes to support adding new counters. Due to an
oversight in the original design, older deserializers are not forwards-compatible;
they throw errors when encountering an unknown counter type. To manage this,
the following changes are made:

1) The defaultImpl NilQueryCounterSnapshot is added to QueryCounterSnapshot's
   deserialization configuration. This means that any unrecognized counter types
   will be read as "nil" by deserializers. Going forward, once all servers are
   on the latest code, this is enough to enable easily adding new counters.

2) A new context parameter "includeAllCounters" is added, which defaults to "false".
   When this parameter is set "false", only legacy counters are included. When set
   to "true", all counters are included. This is currently undocumented. In a future
   version, we should set the default to "true", and at that time, include a release
   note that people updating from versions prior to Druid 31 should set this to
   "false" until their upgrade is complete.

* Style, coverage.

* Fix.
edgar2020 pushed a commit to edgar2020/druid that referenced this pull request Sep 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area - Batch Ingestion Area - MSQ For multi stage queries - https://github.com/apache/druid/issues/12262
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants