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

[Optimization] Cluster State Update Optimization #7853

Merged
merged 24 commits into from
Jul 10, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
7409e4d
Draft Cluster State Update Optimization
sandeshkr419 May 31, 2023
22e435f
Removing explicit skip computation variable for computing all indices…
sandeshkr419 Jun 2, 2023
bae5446
Minor formatting
sandeshkr419 Jun 2, 2023
37ca81d
Add Chengelog
sandeshkr419 Jun 2, 2023
fa1374a
Merge branch 'main' into indicesLookup
sandeshkr419 Jun 2, 2023
62a3f69
Refactor
sandeshkr419 Jun 2, 2023
198a11b
Add Chengelog
sandeshkr419 Jun 2, 2023
ecec7c8
Change customs comparison to data stream comparison only
sandeshkr419 Jun 8, 2023
cc41985
Merge branch 'main' into indicesLookup
sandeshkr419 Jun 8, 2023
35b1c8a
Fix dataStreamPreviousMetadata NPE
sandeshkr419 Jun 8, 2023
01fcd3a
Remove dead code
sandeshkr419 Jun 8, 2023
59af76e
Spotless fix
sandeshkr419 Jun 8, 2023
e347287
Tests fix for NPE
sandeshkr419 Jun 8, 2023
264a435
Utilize previousMetadata to insted of multiple variable copies
sandeshkr419 Jun 19, 2023
7b81fb2
Merge branch 'main' into indicesLookup
sandeshkr419 Jun 19, 2023
b03507f
Merge branch 'main' into indicesLookup
sandeshkr419 Jun 29, 2023
82c78eb
Merge branch 'main' into indicesLookup
sandeshkr419 Jun 29, 2023
00199f9
Remove extra log lines and add test cases
sandeshkr419 Jun 30, 2023
e3cca6f
Refactoring and spotless check
sandeshkr419 Jun 30, 2023
a91edcb
Inclusing tests for metadata comparison in existing test
sandeshkr419 Jun 30, 2023
f16d1ac
Fix test
sandeshkr419 Jun 30, 2023
0e6bf89
Merge branch 'main' into indicesLookup
sandeshkr419 Jul 6, 2023
a9b81f4
Merge branch 'main' into indicesLookup
sandeshkr419 Jul 7, 2023
d0f0135
Merge branch 'main' into indicesLookup
sandeshkr419 Jul 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
### Changed
- Replace jboss-annotations-api_1.2_spec with jakarta.annotation-api ([#7836](https://github.com/opensearch-project/OpenSearch/pull/7836))
- Add min, max, average and thread info to resource stats in tasks API ([#7673](https://github.com/opensearch-project/OpenSearch/pull/7673))
- Optimized Metadata build() to skip redundant computations as part of ClusterState build ([#7853](https://github.com/opensearch-project/OpenSearch/pull/7853))
sandeshkr419 marked this conversation as resolved.
Show resolved Hide resolved

### Deprecated

Expand Down
102 changes: 75 additions & 27 deletions server/src/main/java/org/opensearch/cluster/metadata/Metadata.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
import org.opensearch.common.settings.Setting;
import org.opensearch.common.settings.Setting.Property;
import org.opensearch.common.settings.Settings;
import org.opensearch.common.unit.TimeValue;
import org.opensearch.common.xcontent.XContentHelper;
import org.opensearch.core.common.Strings;
import org.opensearch.core.xcontent.NamedObjectNotFoundException;
Expand Down Expand Up @@ -1119,14 +1120,25 @@ public static class Builder {
private DiffableStringMap hashesOfConsistentSettings = new DiffableStringMap(Collections.emptyMap());

private final Map<String, IndexMetadata> indices;
private final Map<String, IndexMetadata> indicesPreviousState;
private final Map<String, IndexTemplateMetadata> templates;
private final Map<String, Custom> customs;
private final Map<String, Custom> customsPreviousState;
public SortedMap<String, IndexAbstraction> indicesLookup = new TreeMap<>();
private String[] allIndices = new String[0];
private String[] visibleIndices = new String[0];
private String[] allOpenIndices = new String[0];
private String[] visibleOpenIndices = new String[0];
private String[] allClosedIndices = new String[0];
private String[] visibleClosedIndices = new String[0];

public Builder() {
clusterUUID = UNKNOWN_CLUSTER_UUID;
indices = new HashMap<>();
indicesPreviousState = new HashMap<>();
templates = new HashMap<>();
customs = new HashMap<>();
customsPreviousState = new HashMap<>();
indexGraveyard(IndexGraveyard.builder().build()); // create new empty index graveyard to initialize
}

Expand All @@ -1139,8 +1151,17 @@ public Builder(Metadata metadata) {
this.hashesOfConsistentSettings = metadata.hashesOfConsistentSettings;
this.version = metadata.version;
this.indices = new HashMap<>(metadata.indices);
this.indicesPreviousState = new HashMap<>(metadata.indices); // required for comparing with updated indices
this.templates = new HashMap<>(metadata.templates);
this.customs = new HashMap<>(metadata.customs);
this.customsPreviousState = new HashMap<>(metadata.customs);
this.indicesLookup = new TreeMap<>(metadata.indicesLookup);
this.allIndices = Arrays.copyOf(metadata.allIndices, metadata.allIndices.length);
this.visibleIndices = Arrays.copyOf(metadata.visibleIndices, metadata.visibleIndices.length);
this.allOpenIndices = Arrays.copyOf(metadata.allOpenIndices, metadata.allOpenIndices.length);
this.visibleOpenIndices = Arrays.copyOf(metadata.visibleOpenIndices, metadata.visibleOpenIndices.length);
this.allClosedIndices = Arrays.copyOf(metadata.allClosedIndices, metadata.allClosedIndices.length);
this.visibleClosedIndices = Arrays.copyOf(metadata.visibleClosedIndices, metadata.visibleClosedIndices.length);
sandeshkr419 marked this conversation as resolved.
Show resolved Hide resolved
sandeshkr419 marked this conversation as resolved.
Show resolved Hide resolved
}

public Builder put(IndexMetadata.Builder indexMetadataBuilder) {
Expand Down Expand Up @@ -1425,6 +1446,45 @@ public Builder generateClusterUuidIfNeeded() {
}

public Metadata build() {
TimeValue buildStartTime = TimeValue.timeValueMillis(System.nanoTime());
boolean recomputeRequired = indices.equals(indicesPreviousState) == false || customs.equals(customsPreviousState) == false;
sandeshkr419 marked this conversation as resolved.
Show resolved Hide resolved
TimeValue recomputeEndTime = TimeValue.timeValueMillis(System.nanoTime());
logger.info(
"Recompute required: {}, time taken for comparing indices: {} ms",
sandeshkr419 marked this conversation as resolved.
Show resolved Hide resolved
recomputeRequired,
(recomputeEndTime.getNanos() - buildStartTime.getNanos()) / 1000000L
);
// Will simplify this later to omit this recomputeRequired variable entirely - it's only used for testing for now
if (recomputeRequired) {
buildMetadataIndicesLookups();
}

Metadata metadata = new Metadata(
clusterUUID,
clusterUUIDCommitted,
version,
coordinationMetadata,
transientSettings,
persistentSettings,
hashesOfConsistentSettings,
indices,
templates,
customs,
allIndices,
visibleIndices,
allOpenIndices,
visibleOpenIndices,
allClosedIndices,
visibleClosedIndices,
indicesLookup
);
TimeValue endBuildTime = TimeValue.timeValueMillis(System.nanoTime());
// Logging for testing only - will remove in future iterations
logger.info("built metadata in {} ms", (endBuildTime.millis() - buildStartTime.millis()) / 1000000L);
return metadata;
}

private void buildMetadataIndicesLookups() {
// TODO: We should move these datastructures to IndexNameExpressionResolver, this will give the following benefits:
sandeshkr419 marked this conversation as resolved.
Show resolved Hide resolved
// 1) The datastructures will be rebuilt only when needed. Now during serializing we rebuild these datastructures
// while these datastructures aren't even used.
Expand Down Expand Up @@ -1511,40 +1571,28 @@ public Metadata build() {
);
}

SortedMap<String, IndexAbstraction> indicesLookup = Collections.unmodifiableSortedMap(buildIndicesLookup());
TimeValue startTime = TimeValue.timeValueNanos(System.nanoTime());
indicesLookup = Collections.unmodifiableSortedMap(buildIndicesLookup());
TimeValue endTime = TimeValue.timeValueNanos(System.nanoTime());
// Logging for testing only - will remove in future iterations
logger.info(
"rebuilt indicesLookupMap in {} ms, {} entries",
(endTime.nanos() - startTime.nanos()) / 1000000L,
indicesLookup != null ? indicesLookup.size() : 0
);

validateDataStreams(indicesLookup, (DataStreamMetadata) customs.get(DataStreamMetadata.TYPE));

// build all concrete indices arrays:
// TODO: I think we can remove these arrays. it isn't worth the effort, for operations on all indices.
// When doing an operation across all indices, most of the time is spent on actually going to all shards and
// do the required operations, the bottleneck isn't resolving expressions into concrete indices.
String[] allIndicesArray = allIndices.toArray(Strings.EMPTY_ARRAY);
String[] visibleIndicesArray = visibleIndices.toArray(Strings.EMPTY_ARRAY);
String[] allOpenIndicesArray = allOpenIndices.toArray(Strings.EMPTY_ARRAY);
String[] visibleOpenIndicesArray = visibleOpenIndices.toArray(Strings.EMPTY_ARRAY);
String[] allClosedIndicesArray = allClosedIndices.toArray(Strings.EMPTY_ARRAY);
String[] visibleClosedIndicesArray = visibleClosedIndices.toArray(Strings.EMPTY_ARRAY);

return new Metadata(
clusterUUID,
clusterUUIDCommitted,
version,
coordinationMetadata,
transientSettings,
persistentSettings,
hashesOfConsistentSettings,
indices,
templates,
customs,
allIndicesArray,
visibleIndicesArray,
allOpenIndicesArray,
visibleOpenIndicesArray,
allClosedIndicesArray,
visibleClosedIndicesArray,
indicesLookup
);
this.allIndices = allIndices.toArray(new String[allIndices.size()]);
this.allOpenIndices = allOpenIndices.toArray(new String[allOpenIndices.size()]);
this.allClosedIndices = allClosedIndices.toArray(new String[allClosedIndices.size()]);
this.visibleIndices = visibleIndices.toArray(new String[visibleIndices.size()]);
this.visibleOpenIndices = visibleOpenIndices.toArray(new String[visibleOpenIndices.size()]);
this.visibleClosedIndices = visibleClosedIndices.toArray(new String[visibleClosedIndices.size()]);
sandeshkr419 marked this conversation as resolved.
Show resolved Hide resolved
}

private SortedMap<String, IndexAbstraction> buildIndicesLookup() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,10 +292,13 @@ private void runTasks(TaskInputs taskInputs) {
}

final long computationStartTime = threadPool.relativeTimeInMillis();
TimeValue startTime = TimeValue.timeValueMillis(System.currentTimeMillis());
final TaskOutputs taskOutputs = calculateTaskOutputs(taskInputs, previousClusterState);
taskOutputs.notifyFailedTasks();
final TimeValue computationTime = getTimeSince(computationStartTime);
logExecutionTime(computationTime, "compute cluster state update", summary);
TimeValue endTime = TimeValue.timeValueMillis(System.currentTimeMillis());
// Temporarily logging time diff from System time since threadpool time is not precise for less than 200ms
logExecutionTime(TimeValue.timeValueMillis(endTime.millis() - startTime.millis()), "compute cluster state update", summary);

if (taskOutputs.clusterStateUnchanged()) {
final long notificationStartTime = threadPool.relativeTimeInMillis();
Expand Down