Skip to content

Commit c6e3185

Browse files
authored
Add optimized / direct read stats for non-cached files (#54439)
This committ adds support for tracking stats about optimized (ie read ahead) and non optimized (ie direct) read operations executed for non cached Lucene files of searchable snapshot directories. Relates #50999
1 parent f879268 commit c6e3185

File tree

15 files changed

+462
-237
lines changed

15 files changed

+462
-237
lines changed

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/searchablesnapshots/SearchableSnapshotShardStats.java

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -118,14 +118,12 @@ public int hashCode() {
118118
return Objects.hash(shardRouting, snapshotId, indexId, inputStats);
119119
}
120120

121-
122121
public static class CacheIndexInputStats implements Writeable, ToXContentObject {
123122

124123
private final String fileName;
125124
private final long fileLength;
126125

127126
private final long openCount;
128-
private final long innerCount;
129127
private final long closeCount;
130128

131129
private final Counter forwardSmallSeeks;
@@ -137,17 +135,17 @@ public static class CacheIndexInputStats implements Writeable, ToXContentObject
137135
private final Counter cachedBytesRead;
138136
private final TimedCounter cachedBytesWritten;
139137
private final TimedCounter directBytesRead;
138+
private final TimedCounter optimizedBytesRead;
140139

141-
public CacheIndexInputStats(String fileName, long fileLength, long openCount, long innerCount, long closeCount,
140+
public CacheIndexInputStats(String fileName, long fileLength, long openCount, long closeCount,
142141
Counter forwardSmallSeeks, Counter backwardSmallSeeks,
143142
Counter forwardLargeSeeks, Counter backwardLargeSeeks,
144143
Counter contiguousReads, Counter nonContiguousReads,
145144
Counter cachedBytesRead, TimedCounter cachedBytesWritten,
146-
TimedCounter directBytesRead) {
145+
TimedCounter directBytesRead, TimedCounter optimizedBytesRead) {
147146
this.fileName = fileName;
148147
this.fileLength = fileLength;
149148
this.openCount = openCount;
150-
this.innerCount = innerCount;
151149
this.closeCount = closeCount;
152150
this.forwardSmallSeeks = forwardSmallSeeks;
153151
this.backwardSmallSeeks = backwardSmallSeeks;
@@ -158,13 +156,13 @@ public CacheIndexInputStats(String fileName, long fileLength, long openCount, lo
158156
this.cachedBytesRead = cachedBytesRead;
159157
this.cachedBytesWritten = cachedBytesWritten;
160158
this.directBytesRead = directBytesRead;
159+
this.optimizedBytesRead = optimizedBytesRead;
161160
}
162161

163162
CacheIndexInputStats(final StreamInput in) throws IOException {
164163
this.fileName = in.readString();
165164
this.fileLength = in.readVLong();
166165
this.openCount = in.readVLong();
167-
this.innerCount = in.readVLong();
168166
this.closeCount = in.readVLong();
169167
this.forwardSmallSeeks = new Counter(in);
170168
this.backwardSmallSeeks = new Counter(in);
@@ -175,14 +173,14 @@ public CacheIndexInputStats(String fileName, long fileLength, long openCount, lo
175173
this.cachedBytesRead = new Counter(in);
176174
this.cachedBytesWritten = new TimedCounter(in);
177175
this.directBytesRead = new TimedCounter(in);
176+
this.optimizedBytesRead = new TimedCounter(in);
178177
}
179178

180179
@Override
181180
public void writeTo(StreamOutput out) throws IOException {
182181
out.writeString(fileName);
183182
out.writeVLong(fileLength);
184183
out.writeVLong(openCount);
185-
out.writeVLong(innerCount);
186184
out.writeVLong(closeCount);
187185

188186
forwardSmallSeeks.writeTo(out);
@@ -194,6 +192,7 @@ public void writeTo(StreamOutput out) throws IOException {
194192
cachedBytesRead.writeTo(out);
195193
cachedBytesWritten.writeTo(out);
196194
directBytesRead.writeTo(out);
195+
optimizedBytesRead.writeTo(out);
197196
}
198197

199198
public String getFileName() {
@@ -208,10 +207,6 @@ public long getOpenCount() {
208207
return openCount;
209208
}
210209

211-
public long getInnerCount() {
212-
return innerCount;
213-
}
214-
215210
public long getCloseCount() {
216211
return closeCount;
217212
}
@@ -252,20 +247,24 @@ public TimedCounter getDirectBytesRead() {
252247
return directBytesRead;
253248
}
254249

250+
public TimedCounter getOptimizedBytesRead() {
251+
return optimizedBytesRead;
252+
}
253+
255254
@Override
256255
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
257256
builder.startObject();
258257
{
259258
builder.field("name", getFileName());
260259
builder.field("length", getFileLength());
261260
builder.field("open_count", getOpenCount());
262-
builder.field("inner_count", getInnerCount());
263261
builder.field("close_count", getCloseCount());
264262
builder.field("contiguous_bytes_read", getContiguousReads());
265263
builder.field("non_contiguous_bytes_read", getNonContiguousReads());
266264
builder.field("cached_bytes_read", getCachedBytesRead());
267265
builder.field("cached_bytes_written", getCachedBytesWritten());
268266
builder.field("direct_bytes_read", getDirectBytesRead());
267+
builder.field("optimized_bytes_read", getOptimizedBytesRead());
269268
{
270269
builder.startObject("forward_seeks");
271270
builder.field("small", getForwardSmallSeeks());
@@ -293,7 +292,6 @@ public boolean equals(Object other) {
293292
CacheIndexInputStats stats = (CacheIndexInputStats) other;
294293
return fileLength == stats.fileLength
295294
&& openCount == stats.openCount
296-
&& innerCount == stats.innerCount
297295
&& closeCount == stats.closeCount
298296
&& Objects.equals(fileName, stats.fileName)
299297
&& Objects.equals(forwardSmallSeeks, stats.forwardSmallSeeks)
@@ -304,17 +302,18 @@ public boolean equals(Object other) {
304302
&& Objects.equals(nonContiguousReads, stats.nonContiguousReads)
305303
&& Objects.equals(cachedBytesRead, stats.cachedBytesRead)
306304
&& Objects.equals(cachedBytesWritten, stats.cachedBytesWritten)
307-
&& Objects.equals(directBytesRead, stats.directBytesRead);
305+
&& Objects.equals(directBytesRead, stats.directBytesRead)
306+
&& Objects.equals(optimizedBytesRead, stats.optimizedBytesRead);
308307
}
309308

310309
@Override
311310
public int hashCode() {
312-
return Objects.hash(fileName, fileLength, openCount, innerCount, closeCount,
311+
return Objects.hash(fileName, fileLength, openCount, closeCount,
313312
forwardSmallSeeks, backwardSmallSeeks,
314313
forwardLargeSeeks, backwardLargeSeeks,
315314
contiguousReads, nonContiguousReads,
316315
cachedBytesRead, cachedBytesWritten,
317-
directBytesRead);
316+
directBytesRead, optimizedBytesRead);
318317
}
319318
}
320319

x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/searchablesnapshots/SearchableSnapshotShardStatsTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,12 @@ protected SearchableSnapshotShardStats createTestInstance() {
4242

4343
private CacheIndexInputStats randomCacheIndexInputStats() {
4444
return new CacheIndexInputStats(randomAlphaOfLength(10), randomNonNegativeLong(),
45-
randomNonNegativeLong(), randomNonNegativeLong(), randomNonNegativeLong(),
45+
randomNonNegativeLong(), randomNonNegativeLong(),
4646
randomCounter(), randomCounter(),
4747
randomCounter(), randomCounter(),
4848
randomCounter(), randomCounter(),
4949
randomCounter(), randomTimedCounter(),
50-
randomTimedCounter());
50+
randomTimedCounter(), randomTimedCounter());
5151
}
5252

5353
private Counter randomCounter() {

x-pack/plugin/searchable-snapshots/qa/rest/src/test/resources/rest-api-spec/test/stats.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,6 @@ teardown:
147147
- is_true: indices.docs.shards.0.0.files.0.name
148148
- gt: { indices.docs.shards.0.0.files.0.length: 0 }
149149
- gt: { indices.docs.shards.0.0.files.0.open_count: 0 }
150-
- gte: { indices.docs.shards.0.0.files.0.inner_count: 0 }
151150
- gt: { indices.docs.shards.0.0.files.0.close_count: 0 }
152151

153152
- gte: { indices.docs.shards.0.0.files.0.contiguous_bytes_read.count: 0 }
@@ -179,6 +178,13 @@ teardown:
179178
- gte: { indices.docs.shards.0.0.files.0.direct_bytes_read.time_in_nanos: 0 }
180179
- is_false: indices.docs.shards.0.0.files.0.direct_bytes_read.time
181180

181+
- gte: { indices.docs.shards.0.0.files.0.optimized_bytes_read.count: 0 }
182+
- gte: { indices.docs.shards.0.0.files.0.optimized_bytes_read.sum: 0 }
183+
- gte: { indices.docs.shards.0.0.files.0.optimized_bytes_read.min: 0 }
184+
- gte: { indices.docs.shards.0.0.files.0.optimized_bytes_read.max: 0 }
185+
- gte: { indices.docs.shards.0.0.files.0.optimized_bytes_read.time_in_nanos: 0 }
186+
- is_false: indices.docs.shards.0.0.files.0.optimized_bytes_read.time
187+
182188
- gte: { indices.docs.shards.0.0.files.0.forward_seeks.small.count: 0 }
183189
- gte: { indices.docs.shards.0.0.files.0.forward_seeks.small.sum: 0 }
184190
- gte: { indices.docs.shards.0.0.files.0.forward_seeks.small.min: 0 }

x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/index/store/BaseSearchableSnapshotIndexInput.java

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,33 +16,88 @@
1616
import java.io.IOException;
1717
import java.io.InputStream;
1818
import java.util.Objects;
19+
import java.util.concurrent.atomic.AtomicBoolean;
1920

2021
public abstract class BaseSearchableSnapshotIndexInput extends BufferedIndexInput {
2122

2223
protected final BlobContainer blobContainer;
2324
protected final FileInfo fileInfo;
2425
protected final IOContext context;
26+
protected final IndexInputStats stats;
27+
protected final long offset;
28+
protected final long length;
2529

26-
public BaseSearchableSnapshotIndexInput(String resourceDesc, BlobContainer blobContainer, FileInfo fileInfo, IOContext context) {
30+
// the following are only mutable so they can be adjusted after cloning/slicing
31+
protected volatile boolean isClone;
32+
private AtomicBoolean closed;
33+
34+
public BaseSearchableSnapshotIndexInput(
35+
String resourceDesc,
36+
BlobContainer blobContainer,
37+
FileInfo fileInfo,
38+
IOContext context,
39+
IndexInputStats stats,
40+
long offset,
41+
long length
42+
) {
2743
super(resourceDesc, context);
2844
this.blobContainer = Objects.requireNonNull(blobContainer);
2945
this.fileInfo = Objects.requireNonNull(fileInfo);
3046
this.context = Objects.requireNonNull(context);
3147
assert fileInfo.metadata().hashEqualsContents() == false
3248
: "this method should only be used with blobs that are NOT stored in metadata's hash field (fileInfo: " + fileInfo + ')';
49+
this.stats = Objects.requireNonNull(stats);
50+
this.offset = offset;
51+
this.length = length;
52+
this.closed = new AtomicBoolean(false);
53+
this.isClone = false;
3354
}
3455

3556
public BaseSearchableSnapshotIndexInput(
3657
String resourceDesc,
3758
BlobContainer blobContainer,
3859
FileInfo fileInfo,
3960
IOContext context,
61+
IndexInputStats stats,
62+
long offset,
63+
long length,
4064
int bufferSize
4165
) {
42-
this(resourceDesc, blobContainer, fileInfo, context);
66+
this(resourceDesc, blobContainer, fileInfo, context, stats, offset, length);
4367
setBufferSize(bufferSize);
4468
}
4569

70+
@Override
71+
public final long length() {
72+
return length;
73+
}
74+
75+
@Override
76+
public BaseSearchableSnapshotIndexInput clone() {
77+
final BaseSearchableSnapshotIndexInput clone = (BaseSearchableSnapshotIndexInput) super.clone();
78+
clone.closed = new AtomicBoolean(false);
79+
clone.isClone = true;
80+
return clone;
81+
}
82+
83+
protected void ensureOpen() throws IOException {
84+
if (closed.get()) {
85+
throw new IOException(toString() + " is closed");
86+
}
87+
}
88+
89+
@Override
90+
public final void close() throws IOException {
91+
if (closed.compareAndSet(false, true)) {
92+
if (isClone == false) {
93+
stats.incrementCloseCount();
94+
}
95+
innerClose();
96+
}
97+
}
98+
99+
public abstract void innerClose() throws IOException;
100+
46101
protected InputStream openInputStream(final long position, final long length) throws IOException {
47102
assert assertCurrentThreadMayAccessBlobStore();
48103
final long startPart = getPartNumberForPosition(position);

x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/index/store/IndexInputStats.java

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import java.util.concurrent.atomic.AtomicLong;
1414
import java.util.concurrent.atomic.LongAdder;
1515
import java.util.function.LongConsumer;
16+
import java.util.function.LongSupplier;
1617

1718
/**
1819
* {@link IndexInputStats} records stats for a given {@link CachedBlobContainerIndexInput}.
@@ -24,9 +25,9 @@ public class IndexInputStats {
2425

2526
private final long fileLength;
2627
private final long seekingThreshold;
28+
private final LongSupplier currentTimeNanos;
2729

2830
private final LongAdder opened = new LongAdder();
29-
private final LongAdder inner = new LongAdder();
3031
private final LongAdder closed = new LongAdder();
3132

3233
private final Counter forwardSmallSeeks = new Counter();
@@ -39,25 +40,30 @@ public class IndexInputStats {
3940
private final Counter nonContiguousReads = new Counter();
4041

4142
private final TimedCounter directBytesRead = new TimedCounter();
43+
private final TimedCounter optimizedBytesRead = new TimedCounter();
4244

4345
private final Counter cachedBytesRead = new Counter();
4446
private final TimedCounter cachedBytesWritten = new TimedCounter();
4547

46-
public IndexInputStats(long fileLength) {
47-
this(fileLength, SEEKING_THRESHOLD.getBytes());
48+
public IndexInputStats(long fileLength, LongSupplier currentTimeNanos) {
49+
this(fileLength, SEEKING_THRESHOLD.getBytes(), currentTimeNanos);
4850
}
4951

50-
public IndexInputStats(long fileLength, long seekingThreshold) {
52+
public IndexInputStats(long fileLength, long seekingThreshold, LongSupplier currentTimeNanos) {
5153
this.fileLength = fileLength;
5254
this.seekingThreshold = seekingThreshold;
55+
this.currentTimeNanos = currentTimeNanos;
5356
}
5457

55-
public void incrementOpenCount() {
56-
opened.increment();
58+
/**
59+
* @return the current time in nanoseconds that should be used to measure statistics.
60+
*/
61+
public long currentTimeNanos() {
62+
return currentTimeNanos.getAsLong();
5763
}
5864

59-
public void incrementInnerOpenCount() {
60-
inner.increment();
65+
public void incrementOpenCount() {
66+
opened.increment();
6167
}
6268

6369
public void incrementCloseCount() {
@@ -76,6 +82,10 @@ public void addDirectBytesRead(int bytesRead, long nanoseconds) {
7682
directBytesRead.add(bytesRead, nanoseconds);
7783
}
7884

85+
public void addOptimizedBytesRead(int bytesRead, long nanoseconds) {
86+
optimizedBytesRead.add(bytesRead, nanoseconds);
87+
}
88+
7989
public void incrementBytesRead(long previousPosition, long currentPosition, int bytesRead) {
8090
LongConsumer incBytesRead = (previousPosition == currentPosition) ? contiguousReads::add : nonContiguousReads::add;
8191
incBytesRead.accept(bytesRead);
@@ -110,10 +120,6 @@ public LongAdder getOpened() {
110120
return opened;
111121
}
112122

113-
public LongAdder getInnerOpened() {
114-
return inner;
115-
}
116-
117123
public LongAdder getClosed() {
118124
return closed;
119125
}
@@ -146,6 +152,10 @@ public TimedCounter getDirectBytesRead() {
146152
return directBytesRead;
147153
}
148154

155+
public TimedCounter getOptimizedBytesRead() {
156+
return optimizedBytesRead;
157+
}
158+
149159
public Counter getCachedBytesRead() {
150160
return cachedBytesRead;
151161
}

0 commit comments

Comments
 (0)