Skip to content

Commit 88dff2f

Browse files
authored
Merge pull request #5830 from reinhapa/serialize-statistics
[fix] always serialize statistics
2 parents 7a5025b + 0f8306a commit 88dff2f

File tree

1 file changed

+72
-83
lines changed

1 file changed

+72
-83
lines changed

exist-core/src/main/java/org/exist/xquery/PerformanceStatsImpl.java

Lines changed: 72 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,39 @@
4848
*/
4949
@NotThreadSafe
5050
public class PerformanceStatsImpl implements PerformanceStats {
51+
private static final String CALLS = "calls";
52+
private static final String CDATA = "CDATA";
53+
private static final String ELAPSED = "elapsed";
54+
private static final String NAME = "name";
55+
private static final String OPTIMIZATION_LEVEL = "optimization-level";
56+
private static final String QUERY = "query";
57+
private static final String SOURCE = "source";
58+
private static final String TYPE = "type";
5159

52-
private static class IndexStats {
60+
private final Map<String, QueryStats> queries = new HashMap<>();
61+
private final Map<FunctionStats, FunctionStats> functions = new HashMap<>();
62+
private final Map<IndexStats, IndexStats> indexStats = new HashMap<>();
63+
private final Set<OptimizationStats> optimizations = new HashSet<>();
64+
private final Enabler enabler;
65+
66+
private boolean enabled;
5367

68+
public PerformanceStatsImpl(final boolean enabled) {
69+
this(enabled, x -> x);
70+
}
71+
72+
public PerformanceStatsImpl(final boolean enabled, final Enabler enabler) {
73+
this.enabled = enabled;
74+
this.enabler = enabler;
75+
}
76+
77+
private static class IndexStats {
5478
final String source;
5579
final String indexType;
5680
final int line;
5781
final int column;
5882
final IndexOptimizationLevel indexOptimizationLevel;
83+
5984
int usageCount = 1;
6085
long executionTime = 0;
6186

@@ -95,13 +120,13 @@ public boolean equals(final Object obj) {
95120
}
96121

97122
private static class QueryStats {
98-
99123
final String source;
124+
100125
long executionTime = 0;
101126
int callCount = 1;
102127

103128
QueryStats(final String source) {
104-
this.source = (source != null ? source : "");
129+
this.source = source == null ? "" : source;
105130
}
106131

107132
public static QueryStats copy(final QueryStats other) {
@@ -162,36 +187,16 @@ public boolean equals(final Object obj) {
162187
}
163188

164189
@ThreadSafe
165-
private static class OptimizationStats {
166-
final String source;
167-
final OptimizationType type;
168-
final int line;
169-
final int column;
170-
190+
private record OptimizationStats(String source, OptimizationType type, int line, int column) {
171191
OptimizationStats(final String source, final OptimizationType type, final int line, final int column) {
172-
this.source = source != null ? source : "";
192+
this.source = source == null ? "" : source;
173193
this.type = type;
174194
this.line = line;
175195
this.column = column;
176196
}
177-
178-
@Override
179-
public int hashCode() {
180-
return 32 * type.hashCode() + source.hashCode() + line + column;
181-
}
182-
183-
@Override
184-
public boolean equals(final Object obj) {
185-
if (obj instanceof OptimizationStats other) {
186-
return source.equals(other.source) && type == other.type &&
187-
line == other.line && column == other.column;
188-
}
189-
return false;
190-
}
191197
}
192198

193199
private static class CompareByTime implements Comparator<FunctionStats> {
194-
195200
@Override
196201
public int compare(final FunctionStats o1, final FunctionStats o2) {
197202
return Long.compare(o1.executionTime, o2.executionTime);
@@ -203,24 +208,6 @@ public interface Enabler {
203208
boolean enabled(final boolean enabled);
204209
}
205210

206-
private final Map<String, QueryStats> queries = new HashMap<>();
207-
private final Map<FunctionStats, FunctionStats> functions = new HashMap<>();
208-
private final Map<IndexStats, IndexStats> indexStats = new HashMap<>();
209-
private final Set<OptimizationStats> optimizations = new HashSet<>();
210-
211-
private final Enabler enabler;
212-
213-
private boolean enabled = false;
214-
215-
public PerformanceStatsImpl(final boolean enabled) {
216-
this(enabled, x -> x);
217-
}
218-
219-
public PerformanceStatsImpl(final boolean enabled, final Enabler enabler) {
220-
this.enabled = enabled;
221-
this.enabler = enabler;
222-
}
223-
224211
@Override
225212
public void setEnabled(final boolean enabled) {
226213
this.enabled = enabled;
@@ -363,48 +350,50 @@ private FunctionStats[] sort() {
363350

364351
@Override
365352
public void serialize(final MemTreeBuilder builder) {
366-
builder.startElement(new QName(XML_ELEMENT_CALLS, XML_NAMESPACE, XML_PREFIX), null);
367-
if (isEnabled()) {
368-
final AttributesImpl attrs = new AttributesImpl();
369-
for (final QueryStats stats : queries.values()) {
370-
attrs.clear();
371-
attrs.addAttribute("", "source", "source", "CDATA", stats.source);
372-
attrs.addAttribute("", "elapsed", "elapsed", "CDATA", Double.toString(stats.executionTime / 1000.0));
373-
attrs.addAttribute("", "calls", "calls", "CDATA", Integer.toString(stats.callCount));
374-
builder.startElement(new QName("query", XML_NAMESPACE, XML_PREFIX), attrs);
375-
builder.endElement();
376-
}
377-
for (final FunctionStats stats : functions.values()) {
378-
attrs.clear();
379-
attrs.addAttribute("", "name", "name", "CDATA", stats.qname.getStringValue());
380-
attrs.addAttribute("", "elapsed", "elapsed", "CDATA", Double.toString(stats.executionTime / 1000.0));
381-
attrs.addAttribute("", "calls", "calls", "CDATA", Integer.toString(stats.callCount));
382-
if (stats.source != null) {
383-
attrs.addAttribute("", "source", "source", "CDATA", stats.source);
384-
}
385-
builder.startElement(new QName("function", XML_NAMESPACE, XML_PREFIX), attrs);
386-
builder.endElement();
387-
}
388-
for (final IndexStats stats : indexStats.values()) {
389-
attrs.clear();
390-
attrs.addAttribute("", "type", "type", "CDATA", stats.indexType);
391-
attrs.addAttribute("", "source", "source", "CDATA", stats.source + " [" + stats.line + ":" +
392-
stats.column + "]");
393-
attrs.addAttribute("", "elapsed", "elapsed", "CDATA", Double.toString(stats.executionTime / 1000.0));
394-
attrs.addAttribute("", "calls", "calls", "CDATA", Integer.toString(stats.usageCount));
395-
attrs.addAttribute("", "optimization-level", "optimization", "CDATA", stats.indexOptimizationLevel.name());
396-
builder.startElement(new QName("index", XML_NAMESPACE, XML_PREFIX), attrs);
397-
builder.endElement();
353+
final AttributesImpl attrs = new AttributesImpl();
354+
355+
builder.startElement(new QName(XML_ELEMENT_CALLS, XML_NAMESPACE, XML_PREFIX), attrs);
356+
// query statistics
357+
for (final QueryStats stats : queries.values()) {
358+
attrs.clear();
359+
attrs.addAttribute("", SOURCE, SOURCE, CDATA, stats.source);
360+
attrs.addAttribute("", ELAPSED, ELAPSED, CDATA, Double.toString(stats.executionTime / 1000.0));
361+
attrs.addAttribute("", CALLS, CALLS, CDATA, Integer.toString(stats.callCount));
362+
builder.startElement(new QName(QUERY, XML_NAMESPACE, XML_PREFIX), attrs);
363+
builder.endElement();
364+
}
365+
// function statistics
366+
for (final FunctionStats stats : functions.values()) {
367+
attrs.clear();
368+
attrs.addAttribute("", NAME, NAME, CDATA, stats.qname.getStringValue());
369+
attrs.addAttribute("", ELAPSED, ELAPSED, CDATA, Double.toString(stats.executionTime / 1000.0));
370+
attrs.addAttribute("", CALLS, CALLS, CDATA, Integer.toString(stats.callCount));
371+
if (!stats.source.isEmpty()) {
372+
attrs.addAttribute("", SOURCE, SOURCE, CDATA, stats.source);
398373
}
399-
for (final OptimizationStats stats : optimizations) {
400-
attrs.clear();
401-
attrs.addAttribute("", "type", "type", "CDATA", stats.type.toString());
402-
if (stats.source != null) {
403-
attrs.addAttribute("", "source", "source", "CDATA", stats.source + " [" + stats.line + ":" + stats.column + "]");
404-
}
405-
builder.startElement(new QName("optimization", XML_NAMESPACE, XML_PREFIX), attrs);
406-
builder.endElement();
374+
builder.startElement(new QName("function", XML_NAMESPACE, XML_PREFIX), attrs);
375+
builder.endElement();
376+
}
377+
// index statistics
378+
for (final IndexStats stats : indexStats.values()) {
379+
attrs.clear();
380+
attrs.addAttribute("", TYPE, TYPE, CDATA, stats.indexType);
381+
attrs.addAttribute("", SOURCE, SOURCE, CDATA, "%s [%s:%s]".formatted(stats.source, stats.line, stats.column));
382+
attrs.addAttribute("", ELAPSED, ELAPSED, CDATA, Double.toString(stats.executionTime / 1000.0));
383+
attrs.addAttribute("", CALLS, CALLS, CDATA, Integer.toString(stats.usageCount));
384+
attrs.addAttribute("", OPTIMIZATION_LEVEL, OPTIMIZATION_LEVEL, CDATA, stats.indexOptimizationLevel.name());
385+
builder.startElement(new QName("index", XML_NAMESPACE, XML_PREFIX), attrs);
386+
builder.endElement();
387+
}
388+
// optimization statistics
389+
for (final OptimizationStats stats : optimizations) {
390+
attrs.clear();
391+
attrs.addAttribute("", TYPE, TYPE, CDATA, stats.type.toString());
392+
if (stats.source != null) {
393+
attrs.addAttribute("", SOURCE, SOURCE, CDATA, "%s [%s:%s]".formatted(stats.source, stats.line, stats.column));
407394
}
395+
builder.startElement(new QName("optimization", XML_NAMESPACE, XML_PREFIX), attrs);
396+
builder.endElement();
408397
}
409398
builder.endElement();
410399
}

0 commit comments

Comments
 (0)