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

Introduce local block factory #102901

Merged
merged 7 commits into from
Dec 5, 2023
Merged

Introduce local block factory #102901

merged 7 commits into from
Dec 5, 2023

Conversation

dnhatn
Copy link
Member

@dnhatn dnhatn commented Dec 3, 2023

Requesting and returning memory from a CircuitBreaker can be costly due to the involvement of read/write on one or several atomic longs. To address this issue, the local breaker adopts a strategy of over-requesting memory, utilizing the reserved amount for subsequent memory requests without direct access to the actual breaker.

Before passing a Block to another Driver, it is necessary to switch the owning block factory to its parent, which is associated with the global breaker. This is done to bypass the local breaker when releasing memory, as the releasing thread can be any thread, not necessarily the one executing the Driver.

There are two specific operators that need to change the owning block factory: SinkOperator (superset of ExchangeSinkOperator), which is the last operator of a Driver, and AsyncOperator, which can be responded by any thread in response.

The optimization reduces the latency of the enrich operation in the nyc_taxis benchmark from 100ms to 50ms. When combined with #102902, it further reduces the latency to below 40ms, better than the previous performance before the regression.

Relates #102625

public static final String LOCAL_BREAKER_OVER_RESERVED_SIZE_SETTING = "esql.block_factory.local_breaker.over_reserved";
public static final ByteSizeValue LOCAL_BREAKER_OVER_RESERVED_DEFAULT_SIZE = ByteSizeValue.ofKb(4);

public static final String LOCAL_BREAKER_OVER_RESERVED_MAX_SIZE_SETTING = "esql.block_factory.local_breaker.max_over_reserved";
Copy link
Member Author

Choose a reason for hiding this comment

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

These are internal settings now; we can promote them later.

@dnhatn dnhatn marked this pull request as ready for review December 3, 2023 06:43
@elasticsearchmachine elasticsearchmachine added the Team:QL (Deprecated) Meta label for query languages team label Dec 3, 2023
@elasticsearchmachine
Copy link
Collaborator

Pinging @elastic/es-ql (Team:QL)

@elasticsearchmachine
Copy link
Collaborator

Hi @dnhatn, I've created a changelog YAML for you.

@elasticsearchmachine
Copy link
Collaborator

Pinging @elastic/elasticsearch-esql (:Query Languages/ES|QL)

Copy link
Contributor

@ChrisHegarty ChrisHegarty left a comment

Choose a reason for hiding this comment

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

The approach is very nice 👍 . Layering things through a simple hierarchy in block factory, and switching back to the parent before transfer is clever - it allows pages and blocks transferred out seamlessly "give back".

/**
* This method must be called before passing this Block to another Driver.
*/
void allowPassingToDifferentDriver();
Copy link
Contributor

Choose a reason for hiding this comment

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

I see why you called this allowPassingToDifferentDriver, since the block can still be used in the current context, just with its parent breaker. It's kind of a restricted setBlockFactory.

Would you mind locating this method to beside blockFactory(), and also adding a small sentence to the javadoc, say, "Sets this block's blockFactory to the factory's parent" or similar.

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've pushed 341dd8d

return parent != null ? parent : this;
}

public BlockFactory newChildFactory(LocalCircuitBreaker childBreaker) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I like the hierarchy through the block factory. 👍

* @see BlockFactory#newChildFactory(LocalCircuitBreaker)
* @see Block#allowPassingToDifferentDriver()
*/
public final class LocalCircuitBreaker implements CircuitBreaker, Releasable {
Copy link
Contributor

Choose a reason for hiding this comment

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

++

@Override
public final void addInput(Page page) {
// We need to change the ownership of the blocks of the input page before passing them to another driver.
page.allowPassingToDifferentDriver();
Copy link
Contributor

Choose a reason for hiding this comment

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

++ yes, it's important to transfer ownership in the executing thread before the page leaves.

@dnhatn dnhatn requested a review from ChrisHegarty December 4, 2023 16:21
Copy link
Contributor

@ChrisHegarty ChrisHegarty left a comment

Choose a reason for hiding this comment

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

LGTM

@dnhatn
Copy link
Member Author

dnhatn commented Dec 5, 2023

Thank you, Chris!

@dnhatn dnhatn merged commit b734457 into elastic:main Dec 5, 2023
15 checks passed
@dnhatn dnhatn deleted the local-breaker branch December 5, 2023 16:35
dnhatn added a commit that referenced this pull request Dec 6, 2023
This optimization is added for enrich lookups, which are likely to match 
a single document. The change decreases the latency of the enrich
operation in the nyc_taxis benchmark from 100ms to 70ms. When combined
with #102901, it further reduces the latency to below 40ms, better than
the previous performance before the regression.

Relates #102625
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
:Analytics/ES|QL AKA ESQL >enhancement Team:QL (Deprecated) Meta label for query languages team v8.12.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants