Skip to content

Add flag to MetadataDiff to make noop diffs cheaper#90101

Merged
original-brownbear merged 3 commits intoelastic:mainfrom
original-brownbear:skip-noop-metadata-diff
Sep 19, 2022
Merged

Add flag to MetadataDiff to make noop diffs cheaper#90101
original-brownbear merged 3 commits intoelastic:mainfrom
original-brownbear:skip-noop-metadata-diff

Conversation

@original-brownbear
Copy link
Copy Markdown
Contributor

@original-brownbear original-brownbear commented Sep 15, 2022

No need to rebuild a new metadata or send needless bytes if we know before == after. This should save quite a bit of work on data nodes during non-metadata state updates.

relates #77466

No need to rebuild a new metadata or send needless bytes if we know
`before == after`. This should save quite a bit of work on data
nodes during non-metadata state updates.
@original-brownbear original-brownbear added >non-issue :Distributed/Cluster Coordination Cluster formation and cluster state publication, including cluster membership and fault detection. v8.5.0 labels Sep 15, 2022
@elasticsearchmachine elasticsearchmachine added the Team:Distributed Meta label for distributed team. label Sep 15, 2022
@elasticsearchmachine
Copy link
Copy Markdown
Collaborator

Pinging @elastic/es-distributed (Team:Distributed)

return;
}
} else {
noop = false;
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.

Nit: noop is already assigned by this point, no need for the else branch

indices = DiffableUtils.emptyDiff();
templates = DiffableUtils.emptyDiff();
customs = DiffableUtils.emptyDiff();
reservedStateMetadata = DiffableUtils.emptyDiff();
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 wonder if it is possible or worth replacing constructor with a static factory? This way we could have a constant static empty diff

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.

Good point, we don't need a specific instance when reading. We even have a static factory already. I made use of that and reused the existing empty instance in SimpleDiffable now + made the constructor private to avoid abuse.

private final Diff<Map<String, ReservedStateMetadata>> reservedStateMetadata;

// true if this diff is a noop because before and after were the same instance
private final boolean noop;
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 think it is better to name this empty in a context of a diff

@Override
public Metadata apply(Metadata part) {
if (noop) {
return part;
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.

👍

new DiffableUtils.DiffableValueReader<>(ReservedStateMetadata::readFrom, ReservedStateMetadata::readDiffFrom);

MetadataDiff(StreamInput in) throws IOException {
if (in.getVersion().onOrAfter(NOOP_METADATA_DIFF_VERSION)) {
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.

Do we have a unit tests that checks serialization/deserialization of the MetadataDiff? DO we need one for an empty case?

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.

Turns out we don't, it's massively covered by existing tests but it's nice to have a test that makes sure we get instance equality for the empty diff to lock down this optimization. I added one now.

@original-brownbear
Copy link
Copy Markdown
Contributor Author

Thanks Ievgen, all points addressed now I think.

@original-brownbear
Copy link
Copy Markdown
Contributor Author

Thanks Ievgen!

@original-brownbear original-brownbear merged commit 0bbe17a into elastic:main Sep 19, 2022
@original-brownbear original-brownbear deleted the skip-noop-metadata-diff branch September 19, 2022 13:28
original-brownbear added a commit that referenced this pull request Sep 20, 2022
…90164)

With #90101 both follower and leader nodes will get instance equality
on the metadata on non-metadata changes here reliably.
We can leverage that and skip the expensive loop over all indices
in this method on instance equality.
DaveCTurner added a commit to DaveCTurner/elasticsearch that referenced this pull request Dec 9, 2022
The cluster coordination consistency layer relies on a couple of fields
within `Metadata` which record the last _committed_ values on each node.
In contrast, the rest of the cluster state can only be changed at
_accept_ time.

In the past we would copy these fields over from the master on every
publication, but since elastic#90101 we don't copy anything at all if the
`Metadata` is unchanged on the master. However, the master computes the
diff against the last _committed_ state whereas the receiving nodes
apply the diff to the last _accepted_ state, and this means if the
master sends a no-op `Metadata` diff then the receiving node will revert
its last-committed values to the ones included in the state it last
accepted.

With this commit we adjust `CoordinationState` to ignore changes to the
last-committed fields at accept time.
DaveCTurner added a commit to DaveCTurner/elasticsearch that referenced this pull request Dec 9, 2022
The cluster coordination consistency layer relies on a couple of fields
within `Metadata` which record the last _committed_ values on each node.
In contrast, the rest of the cluster state can only be changed at
_accept_ time.

In the past we would copy these fields over from the master on every
publication, but since elastic#90101 we don't copy anything at all if the
`Metadata` is unchanged on the master. However, the master computes the
diff against the last _committed_ state whereas the receiving nodes
apply the diff to the last _accepted_ state, and this means if the
master sends a no-op `Metadata` diff then the receiving node will revert
its last-committed values to the ones included in the state it last
accepted.

With this commit we include the last-committed values alongside the
cluster state diff so that they are always copied properly.
DaveCTurner added a commit to DaveCTurner/elasticsearch that referenced this pull request Dec 11, 2022
The cluster coordination consistency layer relies on a couple of fields
within `Metadata` which record the last _committed_ values on each node.
In contrast, the rest of the cluster state can only be changed at
_accept_ time.

In the past we would copy these fields over from the master on every
publication, but since elastic#90101 we don't copy anything at all if the
`Metadata` is unchanged on the master. However, the master computes the
diff against the last _committed_ state whereas the receiving nodes
apply the diff to the last _accepted_ state, and this means if the
master sends a no-op `Metadata` diff then the receiving node will revert
its last-committed values to the ones included in the state it last
accepted.

With this commit we include the last-committed values alongside the
cluster state diff so that they are always copied properly.
elasticsearchmachine pushed a commit that referenced this pull request Dec 12, 2022
The cluster coordination consistency layer relies on a couple of fields
within `Metadata` which record the last _committed_ values on each node.
In contrast, the rest of the cluster state can only be changed at
_accept_ time.

In the past we would copy these fields over from the master on every
publication, but since #90101 we don't copy anything at all if the
`Metadata` is unchanged on the master. However, the master computes the
diff against the last _committed_ state whereas the receiving nodes
apply the diff to the last _accepted_ state, and this means if the
master sends a no-op `Metadata` diff then the receiving node will revert
its last-committed values to the ones included in the state it last
accepted.

With this commit we include the last-committed values alongside the
cluster state diff so that they are always copied properly.

Closes #90158
DaveCTurner added a commit to DaveCTurner/elasticsearch that referenced this pull request Dec 12, 2022
The cluster coordination consistency layer relies on a couple of fields
within `Metadata` which record the last _committed_ values on each node.
In contrast, the rest of the cluster state can only be changed at
_accept_ time.

In the past we would copy these fields over from the master on every
publication, but since elastic#90101 we don't copy anything at all if the
`Metadata` is unchanged on the master. However, the master computes the
diff against the last _committed_ state whereas the receiving nodes
apply the diff to the last _accepted_ state, and this means if the
master sends a no-op `Metadata` diff then the receiving node will revert
its last-committed values to the ones included in the state it last
accepted.

With this commit we include the last-committed values alongside the
cluster state diff so that they are always copied properly.

Closes elastic#90158
Backport of elastic#92259 to 8.6
DaveCTurner added a commit that referenced this pull request Dec 12, 2022
The cluster coordination consistency layer relies on a couple of fields
within `Metadata` which record the last _committed_ values on each node.
In contrast, the rest of the cluster state can only be changed at
_accept_ time.

In the past we would copy these fields over from the master on every
publication, but since #90101 we don't copy anything at all if the
`Metadata` is unchanged on the master. However, the master computes the
diff against the last _committed_ state whereas the receiving nodes
apply the diff to the last _accepted_ state, and this means if the
master sends a no-op `Metadata` diff then the receiving node will revert
its last-committed values to the ones included in the state it last
accepted.

With this commit we include the last-committed values alongside the
cluster state diff so that they are always copied properly.

Closes #90158
Backport of #92259 to 8.6
@original-brownbear original-brownbear restored the skip-noop-metadata-diff branch April 18, 2023 20:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

:Distributed/Cluster Coordination Cluster formation and cluster state publication, including cluster membership and fault detection. >non-issue Team:Distributed Meta label for distributed team. v8.5.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants