Skip to content

Commit 5d2ce94

Browse files
committed
[pinpoint-apm#12235] Improve windowRangeCount for TimeWindows to be precomputed
1 parent 7a077a7 commit 5d2ce94

File tree

10 files changed

+62
-66
lines changed

10 files changed

+62
-66
lines changed

commons-server/src/main/java/com/navercorp/pinpoint/common/server/util/timewindow/TimeWindow.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ public class TimeWindow implements Iterable<Long>, TimeWindowFunction {
3636

3737
private final Range windowRange;
3838

39+
private final int windowRangeCount;
40+
3941
public TimeWindow(Range range) {
4042
this(range, TimeWindowDownSampler.SAMPLER);
4143
}
@@ -45,6 +47,15 @@ public TimeWindow(Range range, TimeWindowSampler sampler) {
4547
Objects.requireNonNull(sampler, "sampler");
4648
this.windowSlotSize = sampler.getWindowSize(range);
4749
this.windowRange = createWindowRange();
50+
this.windowRangeCount = computeWindowRangeCount(windowRange.durationMillis(), windowSlotSize);
51+
}
52+
53+
/**
54+
* @throws ArithmeticException if the {@code count} overflows an int
55+
*/
56+
private static int computeWindowRangeCount(long duration, long slotSize) {
57+
long count = (duration / slotSize) + 1;
58+
return Math.toIntExact(count);
4859
}
4960

5061
public Iterator<Long> iterator() {
@@ -70,8 +81,8 @@ public long getWindowSlotSize() {
7081
return windowSlotSize;
7182
}
7283

73-
public long getWindowRangeCount() {
74-
return (windowRange.durationMillis() / windowSlotSize) + 1;
84+
public int getWindowRangeCount() {
85+
return windowRangeCount;
7586
}
7687

7788
public Range getWindowSlotRange() {
@@ -94,17 +105,16 @@ public int getWindowIndex(long time) {
94105
private class Itr implements Iterator<Long> {
95106

96107
private long cursor;
108+
private final long end;
97109

98110
public Itr() {
99111
this.cursor = windowRange.getFrom();
112+
this.end = windowRange.getTo();
100113
}
101114

102115
@Override
103116
public boolean hasNext() {
104-
if (cursor > windowRange.getTo()) {
105-
return false;
106-
}
107-
return true;
117+
return cursor <= end;
108118
}
109119

110120
@Override

commons-server/src/test/java/com/navercorp/pinpoint/common/server/util/timewindow/TimeWindowTest.java

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
package com.navercorp.pinpoint.common.server.util.timewindow;
1818

19-
import com.navercorp.pinpoint.common.server.util.timewindow.TimeWindow;
19+
import com.google.common.collect.ImmutableList;
2020
import com.navercorp.pinpoint.common.server.util.time.Range;
2121
import org.apache.logging.log4j.LogManager;
2222
import org.apache.logging.log4j.Logger;
@@ -38,43 +38,34 @@ public void testGetNextWindowFirst() {
3838
TimeWindow window = new TimeWindow(Range.between(0L, 1000));
3939
logger.debug("{}", window.getWindowRange());
4040
Iterator<Long> iterator = window.iterator();
41-
Assertions.assertEquals(iterator.next(), (Long)0L);
41+
Assertions.assertEquals(0L, iterator.next());
4242

43-
Assertions.assertThrows(Exception.class, () -> {
44-
iterator.next();
45-
});
43+
Assertions.assertThrows(Exception.class, iterator::next);
4644

4745
TimeWindow window2 = new TimeWindow(Range.between(0L, TimeUnit.MINUTES.toMillis(1)));
4846
logger.debug("{}", window2.getWindowRange());
4947
Iterator<Long> iterator2 = window2.iterator();
50-
Assertions.assertEquals(iterator2.next(), (Long)0L);
51-
Assertions.assertEquals(iterator2.next(), (Long)(1000*60L));
52-
Assertions.assertThrows(Exception.class, () -> {
53-
iterator2.next();
54-
});
48+
Assertions.assertEquals(0L, iterator2.next());
49+
Assertions.assertEquals(1000*60L, iterator2.next());
50+
Assertions.assertThrows(Exception.class, iterator2::next);
5551
}
5652

5753
@Test
5854
public void testGetNextWindow() {
5955
Range range = Range.between(0L, TimeUnit.MINUTES.toMillis(1));
6056
TimeWindow window = new TimeWindow(range);
61-
int i = 0;
62-
for (Long aLong : window) {
63-
i++;
64-
}
65-
Assertions.assertEquals(i, 2);
57+
ImmutableList<Long> longs = ImmutableList.copyOf(window.iterator());
58+
Assertions.assertEquals(2, longs.size());
59+
Assertions.assertEquals(2, window.getWindowRangeCount());
6660
}
6761

6862
@Test
6963
public void testGetNextWindow2() {
7064
Range range = Range.between(1L, TimeUnit.MINUTES.toMillis(1));
7165
TimeWindow window = new TimeWindow(range);
72-
int i = 0;
73-
for (Long aLong : window) {
74-
logger.debug("{}", aLong);
75-
i++;
76-
}
77-
Assertions.assertEquals(i, 2);
66+
ImmutableList<Long> longs = ImmutableList.copyOf(window.iterator());
67+
Assertions.assertEquals(2, longs.size());
68+
Assertions.assertEquals(2, window.getWindowRangeCount());
7869
}
7970

8071
@Test
@@ -103,16 +94,16 @@ public void refineRange() {
10394
Range windowRange = window.getWindowRange();
10495
// 1 should be replace by 0.
10596
logger.debug("{}", windowRange);
106-
Assertions.assertEquals(windowRange.getFrom(), 0);
107-
Assertions.assertEquals(windowRange.getTo(), TimeUnit.MINUTES.toMillis(1));
97+
Assertions.assertEquals(0, windowRange.getFrom());
98+
Assertions.assertEquals(TimeUnit.MINUTES.toMillis(1), windowRange.getTo());
10899

109100
}
110101

111102
@Test
112103
public void testGetWindowRangeLength() {
113104
Range range = Range.between(1L, 2L);
114105
TimeWindow window = new TimeWindow(range);
115-
long windowRangeLength = window.getWindowRangeCount();
106+
int windowRangeLength = window.getWindowRangeCount();
116107
logger.debug("{}", windowRangeLength);
117108
Assertions.assertEquals(1, windowRangeLength);
118109

@@ -122,7 +113,7 @@ public void testGetWindowRangeLength() {
122113
public void testGetWindowRangeLength2() {
123114
Range range = Range.between(1L, 1000*60L + 1);
124115
TimeWindow window = new TimeWindow(range);
125-
long windowRangeLength = window.getWindowRangeCount();
116+
int windowRangeLength = window.getWindowRangeCount();
126117
logger.debug("{}", windowRangeLength);
127118
Assertions.assertEquals(2, windowRangeLength);
128119
}

metric-module/metric-commons/src/main/java/com/navercorp/pinpoint/metric/common/util/TimeSeriesBuilder.java

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,10 @@ public TimeSeriesBuilder(TimeWindow timeWindow, UncollectedDataCreator<T> uncoll
4444
public List<MinMaxMetricPoint<T>> buildForMinMaxMetricPointList(List<MinMaxMetricPoint<T>> minMaxMetricDataList) {
4545
List<MinMaxMetricPoint<T>> filledMinMaxMetricPointList = createInitialMinMaxMetricPoint();
4646

47+
final int windowRangeCount = timeWindow.getWindowRangeCount();
4748
for (MinMaxMetricPoint<T> minMaxMetricPoint : minMaxMetricDataList) {
4849
int timeslotIndex = this.timeWindow.getWindowIndex(minMaxMetricPoint.getXVal());
49-
if (timeslotIndex < 0 || timeslotIndex >= timeWindow.getWindowRangeCount()) {
50+
if (timeslotIndex < 0 || timeslotIndex >= windowRangeCount) {
5051
continue;
5152
}
5253
filledMinMaxMetricPointList.set(timeslotIndex, minMaxMetricPoint);
@@ -58,9 +59,10 @@ public List<MinMaxMetricPoint<T>> buildForMinMaxMetricPointList(List<MinMaxMetri
5859
public List<AvgMinMetricPoint<T>> buildForAvgMinMetricPointList(List<AvgMinMetricPoint<T>> avgMinMetricDataList) {
5960
List<AvgMinMetricPoint<T>> filledAvgMinMetricPointList = createInitialAvgMinMetricPoint();
6061

62+
final int windowRangeCount = timeWindow.getWindowRangeCount();
6163
for (AvgMinMetricPoint<T> avgMinMetricPoint : avgMinMetricDataList) {
6264
int timeslotIndex = this.timeWindow.getWindowIndex(avgMinMetricPoint.getXVal());
63-
if (timeslotIndex < 0 || timeslotIndex >= timeWindow.getWindowRangeCount()) {
65+
if (timeslotIndex < 0 || timeslotIndex >= windowRangeCount) {
6466
continue;
6567
}
6668
filledAvgMinMetricPointList.set(timeslotIndex, avgMinMetricPoint);
@@ -70,7 +72,7 @@ public List<AvgMinMetricPoint<T>> buildForAvgMinMetricPointList(List<AvgMinMetri
7072
}
7173

7274
private List<AvgMinMetricPoint<T>> createInitialAvgMinMetricPoint() {
73-
int numTimeslots = (int) this.timeWindow.getWindowRangeCount();
75+
int numTimeslots = this.timeWindow.getWindowRangeCount();
7476
List<AvgMinMetricPoint<T>> pointList = new ArrayList<>(numTimeslots);
7577

7678
for (long timestamp : this.timeWindow) {
@@ -81,7 +83,7 @@ private List<AvgMinMetricPoint<T>> createInitialAvgMinMetricPoint() {
8183
}
8284

8385
private List<MinMaxMetricPoint<T>> createInitialMinMaxMetricPoint() {
84-
int numTimeslots = (int) this.timeWindow.getWindowRangeCount();
86+
int numTimeslots = this.timeWindow.getWindowRangeCount();
8587
List<MinMaxMetricPoint<T>> pointList = new ArrayList<>(numTimeslots);
8688

8789
for (long timestamp : this.timeWindow) {
@@ -94,9 +96,10 @@ private List<MinMaxMetricPoint<T>> createInitialMinMaxMetricPoint() {
9496
public List<AvgMinMaxMetricPoint<T>> buildForAvgMinMaxMetricPointList(List<AvgMinMaxMetricPoint<T>> avgMinMaxMetricDataList) {
9597
List<AvgMinMaxMetricPoint<T>> filledAvgMinMaxMetricPointList = createInitialAvgMinMaxMetricPoint();
9698

99+
final int windowRangeCount = timeWindow.getWindowRangeCount();
97100
for (AvgMinMaxMetricPoint<T> avgMinMaxMetricPoint : avgMinMaxMetricDataList) {
98101
int timeslotIndex = this.timeWindow.getWindowIndex(avgMinMaxMetricPoint.getXVal());
99-
if (timeslotIndex < 0 || timeslotIndex >= timeWindow.getWindowRangeCount()) {
102+
if (timeslotIndex < 0 || timeslotIndex >= windowRangeCount) {
100103
continue;
101104
}
102105
filledAvgMinMaxMetricPointList.set(timeslotIndex, avgMinMaxMetricPoint);
@@ -106,7 +109,7 @@ public List<AvgMinMaxMetricPoint<T>> buildForAvgMinMaxMetricPointList(List<AvgMi
106109
}
107110

108111
private List<AvgMinMaxMetricPoint<T>> createInitialAvgMinMaxMetricPoint() {
109-
int numTimeslots = (int) this.timeWindow.getWindowRangeCount();
112+
int numTimeslots = this.timeWindow.getWindowRangeCount();
110113
List<AvgMinMaxMetricPoint<T>> pointList = new ArrayList<>(numTimeslots);
111114

112115
for (long timestamp : this.timeWindow) {
@@ -119,9 +122,10 @@ private List<AvgMinMaxMetricPoint<T>> createInitialAvgMinMaxMetricPoint() {
119122
public List<SystemMetricPoint<T>> build(List<SystemMetricPoint<T>> systemMetricDataList) {
120123
List<SystemMetricPoint<T>> filledSystemMetricPointList = createInitialPoints();
121124

125+
final int windowRangeCount = timeWindow.getWindowRangeCount();
122126
for (SystemMetricPoint<T> systemMetricPoint : systemMetricDataList) {
123127
int timeslotIndex = this.timeWindow.getWindowIndex(systemMetricPoint.getXVal());
124-
if (timeslotIndex < 0 || timeslotIndex >= timeWindow.getWindowRangeCount()) {
128+
if (timeslotIndex < 0 || timeslotIndex >= windowRangeCount) {
125129
continue;
126130
}
127131
filledSystemMetricPointList.set(timeslotIndex, systemMetricPoint);
@@ -131,7 +135,7 @@ public List<SystemMetricPoint<T>> build(List<SystemMetricPoint<T>> systemMetricD
131135
}
132136

133137
private List<SystemMetricPoint<T>> createInitialPoints() {
134-
int numTimeslots = (int) this.timeWindow.getWindowRangeCount();
138+
int numTimeslots = this.timeWindow.getWindowRangeCount();
135139
List<SystemMetricPoint<T>> pointList = new ArrayList<>(numTimeslots);
136140

137141
for (long timestamp : this.timeWindow) {

metric-module/metric-commons/src/main/java/com/navercorp/pinpoint/metric/common/util/TimeUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
public class TimeUtils {
2828

2929
public static List<Long> createTimeStampList(TimeWindow timeWindow) {
30-
List<Long> timestampList = new ArrayList<>((int) timeWindow.getWindowRangeCount());
30+
List<Long> timestampList = new ArrayList<>(timeWindow.getWindowRangeCount());
3131

3232
for (Long timestamp : timeWindow) {
3333
timestampList.add(timestamp);

metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/model/MetricDataSearchKey.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818

1919
import com.navercorp.pinpoint.common.server.util.StringPrecondition;
2020
import com.navercorp.pinpoint.common.server.util.time.Range;
21-
import com.navercorp.pinpoint.common.server.util.timewindow.TimeWindow;
2221
import com.navercorp.pinpoint.common.server.util.timewindow.TimePrecision;
22+
import com.navercorp.pinpoint.common.server.util.timewindow.TimeWindow;
2323

2424
import java.util.Objects;
2525
import java.util.concurrent.TimeUnit;
@@ -46,7 +46,7 @@ public MetricDataSearchKey(String tenantId, String hostGroupName, String hostNam
4646
this.metricDefinitionId = StringPrecondition.requireHasLength(metricDefinitionId, "metricDefinitionId");
4747
Objects.requireNonNull(timeWindow, "timeWindow");
4848
this.range = timeWindow.getWindowRange();
49-
this.timePrecision = TimePrecision.newTimePrecision(TimeUnit.MILLISECONDS, (int) timeWindow.getWindowSlotSize());
49+
this.timePrecision = TimePrecision.newTimePrecision(TimeUnit.MILLISECONDS, timeWindow.getWindowSlotSize());
5050
this.limit = timeWindow.getWindowRangeCount();
5151
}
5252

metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/model/chart/TimeSeriesChartBuilder.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,7 @@ public class TimeSeriesChartBuilder<P extends Point> {
3636
private final Point.UncollectedPointCreator<P> uncollectedPointCreator;
3737

3838
public TimeSeriesChartBuilder(TimeWindow timeWindow, Point.UncollectedPointCreator<P> uncollectedPointCreator) {
39-
if (timeWindow.getWindowRangeCount() > Integer.MAX_VALUE) {
40-
throw new IllegalArgumentException("range yields too many timeslots");
41-
}
42-
this.timeWindow = timeWindow;
39+
this.timeWindow = Objects.requireNonNull(timeWindow, "timeWindow");
4340
this.uncollectedPointCreator = Objects.requireNonNull(uncollectedPointCreator, "uncollectedPointCreator");
4441
}
4542

@@ -48,9 +45,10 @@ public Chart<P> build(List<P> sampledPoints) {
4845
return new Chart<>(Collections.emptyList());
4946
}
5047
List<P> points = createInitialPoints();
48+
final int windowRangeCount = timeWindow.getWindowRangeCount();
5149
for (P sampledPoint : sampledPoints) {
5250
int timeslotIndex = this.timeWindow.getWindowIndex(sampledPoint.getXVal());
53-
if (timeslotIndex < 0 || timeslotIndex >= timeWindow.getWindowRangeCount()) {
51+
if (timeslotIndex < 0 || timeslotIndex >= windowRangeCount) {
5452
continue;
5553
}
5654
points.set(timeslotIndex, sampledPoint);
@@ -79,7 +77,7 @@ private <S> List<P> applyFilter(List<S> sourceList, Function<S, P> filter) {
7977
}
8078

8179
private List<P> createInitialPoints() {
82-
int numTimeslots = (int) this.timeWindow.getWindowRangeCount();
80+
final int numTimeslots = this.timeWindow.getWindowRangeCount();
8381
List<P> points = new ArrayList<>(numTimeslots);
8482
for (long timestamp : this.timeWindow) {
8583
points.add(uncollectedPointCreator.createUnCollectedPoint(timestamp));

metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/view/SystemMetricChartSerializer.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@
1919
import com.fasterxml.jackson.core.JsonGenerator;
2020
import com.fasterxml.jackson.databind.JsonSerializer;
2121
import com.fasterxml.jackson.databind.SerializerProvider;
22-
import com.navercorp.pinpoint.metric.common.model.Tag;
2322
import com.navercorp.pinpoint.common.server.util.timewindow.TimeWindow;
24-
import com.navercorp.pinpoint.metric.web.model.chart.Chart;
23+
import com.navercorp.pinpoint.metric.common.model.Tag;
2524
import com.navercorp.pinpoint.metric.common.model.chart.Point;
25+
import com.navercorp.pinpoint.metric.web.model.chart.Chart;
2626
import com.navercorp.pinpoint.metric.web.model.chart.SystemMetricChart;
2727

2828
import java.io.IOException;
@@ -51,7 +51,7 @@ public void serialize(SystemMetricChart systemMetricChart, JsonGenerator jgen, S
5151
}
5252

5353
private void writeTimestamp(JsonGenerator jgen, TimeWindow timeWindow) throws IOException {
54-
List<Long> timestamps = new ArrayList<>((int) timeWindow.getWindowRangeCount());
54+
List<Long> timestamps = new ArrayList<>(timeWindow.getWindowRangeCount());
5555
for (Long timestamp : timeWindow) {
5656
timestamps.add(timestamp);
5757
}

otlpmetric/otlpmetric-common/src/main/java/com/navercorp/pinpoint/otlp/common/util/TimeSeriesBuilder.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@ public TimeSeriesBuilder(TimeWindow timeWindow, UncollectedDataCreator<T> uncoll
3838

3939
public List<MetricPoint<T>> build(List<MetricPoint<T>> metricDataList) {
4040
List<MetricPoint<T>> filledMetricPointList = createInitialPoints();
41-
41+
final int windowRangeCount = timeWindow.getWindowRangeCount();
4242
for (MetricPoint<T> metricPoint : metricDataList) {
4343
int timeslotIndex = this.timeWindow.getWindowIndex(metricPoint.getXVal());
44-
if (timeslotIndex < 0 || timeslotIndex >= timeWindow.getWindowRangeCount()) {
44+
if (timeslotIndex < 0 || timeslotIndex >= windowRangeCount) {
4545
continue;
4646
}
4747
filledMetricPointList.set(timeslotIndex, metricPoint);
@@ -51,7 +51,7 @@ public List<MetricPoint<T>> build(List<MetricPoint<T>> metricDataList) {
5151
}
5252

5353
private List<MetricPoint<T>> createInitialPoints() {
54-
int numTimeslots = (int) this.timeWindow.getWindowRangeCount();
54+
int numTimeslots = Math.toIntExact(this.timeWindow.getWindowRangeCount());
5555
List<MetricPoint<T>> pointList = new ArrayList<>(numTimeslots);
5656

5757
for (long timestamp : this.timeWindow) {

web/src/main/java/com/navercorp/pinpoint/web/applicationmap/histogram/AgentTimeHistogram.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ private AgentHistogram selectAgentHistogram(String agentName) {
128128
}
129129

130130
public List<DoubleApplicationStatPoint> getApplicationApdexScoreList(TimeWindow window) {
131-
int size = (int) window.getWindowRangeCount();
131+
int size = window.getWindowRangeCount();
132132
List<Double> min = fillList(size, DEFAULT_MIN_APDEX_SCORE);
133133
List<String> minAgentId = fillList(size, DEFAULT_AGENT_ID);
134134
List<Double> max = fillList(size, DEFAULT_MAX_APDEX_SCORE);

web/src/main/java/com/navercorp/pinpoint/web/vo/chart/TimeSeriesChartBuilder.java

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,24 +37,17 @@ public TimeSeriesChartBuilder(Point.UncollectedPointCreator<P> uncollectedPointC
3737
this.uncollectedPointCreator = Objects.requireNonNull(uncollectedPointCreator, "uncollectedPointCreator");
3838
}
3939

40-
private void checkTimeWindow(TimeWindow timeWindow) {
41-
Objects.requireNonNull(timeWindow, "timeWindow");
42-
43-
if (timeWindow.getWindowRangeCount() > Integer.MAX_VALUE) {
44-
throw new IllegalArgumentException("range yields too many timeslots");
45-
}
46-
}
47-
4840
public Chart<P> build(TimeWindow timeWindow, List<P> sampledPoints) {
49-
checkTimeWindow(timeWindow);
41+
Objects.requireNonNull(timeWindow, "timeWindow");
5042

5143
if (CollectionUtils.isEmpty(sampledPoints)) {
5244
return new Chart<>(Collections.emptyList());
5345
}
5446
List<P> points = createInitialPoints(timeWindow);
47+
final int windowRangeCount = timeWindow.getWindowRangeCount();
5548
for (P sampledPoint : sampledPoints) {
5649
int timeslotIndex = timeWindow.getWindowIndex(sampledPoint.getXVal());
57-
if (timeslotIndex < 0 || timeslotIndex >= timeWindow.getWindowRangeCount()) {
50+
if (timeslotIndex < 0 || timeslotIndex >= windowRangeCount) {
5851
continue;
5952
}
6053
points.set(timeslotIndex, sampledPoint);
@@ -83,7 +76,7 @@ private <S> List<P> applyFilter(List<S> sourceList, Function<S, P> filter) {
8376
}
8477

8578
private List<P> createInitialPoints(TimeWindow timeWindow) {
86-
int numTimeslots = (int) timeWindow.getWindowRangeCount();
79+
final int numTimeslots = timeWindow.getWindowRangeCount();
8780
List<P> points = new ArrayList<>(numTimeslots);
8881
for (long timestamp : timeWindow) {
8982
points.add(uncollectedPointCreator.createUnCollectedPoint(timestamp));

0 commit comments

Comments
 (0)