-
Notifications
You must be signed in to change notification settings - Fork 25.8k
Improve EQL Sequence circuit breaker precision #88538
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
Changes from all commits
996b7aa
25c8c99
13a307d
ed726a7
1b275db
33c072f
a949772
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| pr: 88538 | ||
| summary: Improve EQL Sequence circuit breaker precision | ||
| area: EQL | ||
| type: bug | ||
| issues: | ||
| - 88300 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -82,7 +82,10 @@ public void clear() { | |
| private final Stats stats = new Stats(); | ||
|
|
||
| private boolean headLimit = false; | ||
| private long totalRamBytesUsed = 0; | ||
|
|
||
| // circuit breaker accounting | ||
| private long prevRamBytesUsedInFlight = 0; | ||
| private long prevRamBytesUsedCompleted = 0; | ||
|
|
||
| @SuppressWarnings("rawtypes") | ||
| public SequenceMatcher(int stages, boolean descending, TimeValue maxSpan, Limit limit, CircuitBreaker circuitBreaker) { | ||
|
|
@@ -114,9 +117,6 @@ private void trackSequence(Sequence sequence) { | |
| * Returns false if the process needs to be stopped. | ||
| */ | ||
| boolean match(int stage, Iterable<Tuple<KeyAndOrdinal, HitReference>> hits) { | ||
| long ramBytesUsedInFlight = ramBytesUsedInFlight(); | ||
| long ramBytesUsedCompleted = ramBytesUsedCompleted(); | ||
|
|
||
| for (Tuple<KeyAndOrdinal, HitReference> tuple : hits) { | ||
| KeyAndOrdinal ko = tuple.v1(); | ||
| HitReference hit = tuple.v2(); | ||
|
|
@@ -145,7 +145,7 @@ boolean match(int stage, Iterable<Tuple<KeyAndOrdinal, HitReference>> hits) { | |
| log.trace("{}", stats); | ||
| matched = true; | ||
| } | ||
| trackMemory(ramBytesUsedInFlight, ramBytesUsedCompleted); | ||
| trackMemory(); | ||
| return matched; | ||
| } | ||
|
|
||
|
|
@@ -305,34 +305,35 @@ public void clear() { | |
| clearCircuitBreaker(); | ||
| } | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a comment to these two methods stating that they are protected for testing purposes. |
||
| private long ramBytesUsedInFlight() { | ||
| // protected for testing purposes | ||
| protected long ramBytesUsedInFlight() { | ||
| return RamUsageEstimator.sizeOf(keyToSequences) + RamUsageEstimator.sizeOf(stageToKeys); | ||
| } | ||
|
|
||
| private long ramBytesUsedCompleted() { | ||
| // protected for testing purposes | ||
| protected long ramBytesUsedCompleted() { | ||
| return RamUsageEstimator.sizeOfCollection(completed); | ||
| } | ||
|
|
||
| private void addMemory(long bytes, String label) { | ||
| totalRamBytesUsed += bytes; | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In case of breaker failure, the memory is not added to the circuit breaker, so the addition to
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a good point, should this be relatively easy reproducible? |
||
| circuitBreaker.addEstimateBytesAndMaybeBreak(bytes, label); | ||
| } | ||
|
|
||
| private void clearCircuitBreaker() { | ||
| circuitBreaker.addWithoutBreaking(-totalRamBytesUsed); | ||
| totalRamBytesUsed = 0; | ||
| circuitBreaker.addWithoutBreaking(-prevRamBytesUsedInFlight - prevRamBytesUsedCompleted); | ||
| prevRamBytesUsedInFlight = 0; | ||
| prevRamBytesUsedCompleted = 0; | ||
| } | ||
|
|
||
| // The method is called at the end of match() which is called for every sub query in the sequence query | ||
| // and for each subquery every "fetch_size" docs. Doing RAM accounting on object creation is | ||
| // expensive, so we just calculate the difference in bytes of the total memory that the matcher's | ||
| // structure occupy for the in-flight tracking of sequences, as well as for the list of completed | ||
| // sequences. | ||
| private void trackMemory(long prevRamBytesUsedInflight, long prevRamBytesUsedCompleted) { | ||
| long bytesDiff = ramBytesUsedInFlight() - prevRamBytesUsedInflight; | ||
| addMemory(bytesDiff, CB_INFLIGHT_LABEL); | ||
| bytesDiff = ramBytesUsedCompleted() - prevRamBytesUsedCompleted; | ||
| addMemory(bytesDiff, CB_COMPLETED_LABEL); | ||
| private void trackMemory() { | ||
| long newRamBytesUsedInFlight = ramBytesUsedInFlight(); | ||
| circuitBreaker.addEstimateBytesAndMaybeBreak(newRamBytesUsedInFlight - prevRamBytesUsedInFlight, CB_INFLIGHT_LABEL); | ||
| prevRamBytesUsedInFlight = newRamBytesUsedInFlight; | ||
|
|
||
| long newRamBytesUsedCompleted = ramBytesUsedCompleted(); | ||
| circuitBreaker.addEstimateBytesAndMaybeBreak(newRamBytesUsedCompleted - prevRamBytesUsedCompleted, CB_COMPLETED_LABEL); | ||
| prevRamBytesUsedCompleted = newRamBytesUsedCompleted; | ||
| } | ||
|
|
||
| @Override | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These values are > 0, if they reduce for some reason during the execution, at the end the memory diff will be negative.
Setting them to 0 as a global value, and avoiding to re-calculate them at the beginning of
match(), guarantees that the memory added to the circuit breaker is always positive (unless Accountable objects return negative values, but checking the implementations it's not the case)