Skip to content

Commit

Permalink
Fix quadratic complexity in SnapshotStatus serialization (#90795) (#9…
Browse files Browse the repository at this point in the history
…0803)

The loop here is obviously O(N^2) and it shows as taking multiple
seconds to build the by-index map in x-content serialization for
a 25k shards snapshot.
This makes the logic O(N) and fixes some potential issues with
consistency around concurrent access by using a more appropriate
access pattern to the field caching the by-index map.
  • Loading branch information
original-brownbear authored Oct 11, 2022
1 parent d63cc81 commit 4535391
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 20 deletions.
5 changes: 5 additions & 0 deletions docs/changelog/90795.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pr: 90795
summary: Fix quadratic complexity in `SnapshotStatus` serialization
area: Snapshot/Restore
type: bug
issues: []
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,9 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
Expand Down Expand Up @@ -143,29 +141,22 @@ public SnapshotShardsStats getShardsStats() {
* Returns list of snapshot indices
*/
public Map<String, SnapshotIndexStatus> getIndices() {
if (this.indicesStatus != null) {
return this.indicesStatus;
var res = this.indicesStatus;
if (res != null) {
return res;
}

Map<String, SnapshotIndexStatus> indicesStatus = new HashMap<>();

Set<String> indices = new HashSet<>();
Map<String, List<SnapshotIndexShardStatus>> indices = new HashMap<>();
for (SnapshotIndexShardStatus shard : shards) {
indices.add(shard.getIndex());
indices.computeIfAbsent(shard.getIndex(), k -> new ArrayList<>()).add(shard);
}

for (String index : indices) {
List<SnapshotIndexShardStatus> shards = new ArrayList<>();
for (SnapshotIndexShardStatus shard : this.shards) {
if (shard.getIndex().equals(index)) {
shards.add(shard);
}
}
indicesStatus.put(index, new SnapshotIndexStatus(index, shards));
Map<String, SnapshotIndexStatus> indicesStatus = Maps.newMapWithExpectedSize(indices.size());
for (Map.Entry<String, List<SnapshotIndexShardStatus>> entry : indices.entrySet()) {
indicesStatus.put(entry.getKey(), new SnapshotIndexStatus(entry.getKey(), entry.getValue()));
}
this.indicesStatus = unmodifiableMap(indicesStatus);
return this.indicesStatus;

res = unmodifiableMap(indicesStatus);
this.indicesStatus = res;
return res;
}

@Override
Expand Down

0 comments on commit 4535391

Please sign in to comment.