Skip to content

Commit bbe0f3b

Browse files
committed
Smaller optimizations
1 parent fa34809 commit bbe0f3b

14 files changed

Lines changed: 81 additions & 43 deletions

core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/AbstractConnectedRangesSlot.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import ai.timefold.solver.core.impl.score.stream.collector.connected_ranges.ConnectedRangeTracker;
88
import ai.timefold.solver.core.impl.score.stream.collector.connected_ranges.Range;
99

10+
import org.jspecify.annotations.Nullable;
11+
1012
public abstract class AbstractConnectedRangesSlot<Interval_, Point_ extends Comparable<Point_>, Difference_ extends Comparable<Difference_>> {
1113

1214
public static final class State<Interval_, Point_ extends Comparable<Point_>, Difference_ extends Comparable<Difference_>> {
@@ -24,22 +26,20 @@ public ConnectedRangeChain<Interval_, Point_, Difference_> result() {
2426
}
2527

2628
private final State<Interval_, Point_, Difference_> state;
27-
private Range<Interval_, Point_> cachedRange;
29+
private @Nullable Range<Interval_, Point_> cachedRange;
2830

2931
public AbstractConnectedRangesSlot(State<Interval_, Point_, Difference_> state) {
3032
this.state = state;
3133
}
3234

3335
protected void addMapped(Interval_ result) {
34-
final var saved = state.context.getRange(result);
35-
cachedRange = saved;
36-
state.context.add(saved);
36+
cachedRange = state.context.getRange(result);
37+
state.context.add(cachedRange);
3738
}
3839

3940
protected void updateMapped(Interval_ input) {
40-
state.context.remove(cachedRange);
41-
cachedRange = state.context.getRange(input);
42-
state.context.add(cachedRange);
41+
removeMapped();
42+
addMapped(input);
4343
}
4444

4545
protected void removeMapped() {

core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/AbstractCountSlot.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,16 @@
33
public abstract class AbstractCountSlot {
44

55
public static final class State {
6-
long count = 0;
6+
private long count = 0;
7+
private long cachedCount = 0;
8+
private Long boxed = 0L;
79

810
public Long result() {
9-
return count;
11+
if (cachedCount != count) { // Minimize boxing overhead.
12+
boxed = count;
13+
cachedCount = count;
14+
}
15+
return boxed;
1016
}
1117
}
1218

core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/AbstractLongAverageSlot.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
public abstract class AbstractLongAverageSlot {
44

55
public static final class State {
6-
long count = 0;
7-
long sum = 0;
6+
private long count = 0;
7+
private long sum = 0;
88

99
public Double result() {
1010
if (count == 0) {

core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/AbstractLongDistinctSlot.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,21 @@
1111
public abstract class AbstractLongDistinctSlot<Input_> {
1212

1313
public static final class State<Input_> {
14+
1415
private final Map<Input_, MutableInt> countMap = new HashMap<>();
16+
private long cachedSize = 0;
17+
private @Nullable Long boxed = 0L;
1518

1619
public Long result() {
17-
return (long) countMap.size();
20+
var newSize = countMap.size();
21+
if (cachedSize != newSize) {
22+
// The collector's result is generic, we need to avoid boxing overhead as much as possible.
23+
cachedSize = newSize;
24+
boxed = (long) newSize;
25+
}
26+
return boxed;
1827
}
28+
1929
}
2030

2131
private final State<Input_> state;

core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/AbstractLongSumSlot.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,16 @@
33
public abstract class AbstractLongSumSlot {
44

55
public static final class State {
6-
long sum = 0;
6+
private long sum = 0;
7+
private long cachedSum = 0;
8+
private Long boxed = 0L;
79

810
public Long result() {
9-
return sum;
11+
if (cachedSum != sum) { // Minimize boxing overhead.
12+
boxed = sum;
13+
cachedSum = sum;
14+
}
15+
return boxed;
1016
}
1117
}
1218

core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/AbstractMinMaxSlot.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@
1111
import ai.timefold.solver.core.impl.util.ConstantLambdaUtils;
1212
import ai.timefold.solver.core.impl.util.MutableInt;
1313

14+
import org.jspecify.annotations.Nullable;
15+
1416
public abstract class AbstractMinMaxSlot<Result_, Property_> {
1517
public static final class State<Result_, Property_> {
16-
final boolean isMin;
17-
final NavigableMap<Property_, Map<Result_, MutableInt>> propertyToItemCountMap;
18-
final Function<? super Result_, ? extends Property_> propertyFunction;
18+
private final boolean isMin;
19+
private final NavigableMap<Property_, Map<Result_, MutableInt>> propertyToItemCountMap;
20+
private final Function<? super Result_, ? extends Property_> propertyFunction;
1921

20-
State(boolean isMin, NavigableMap<Property_, Map<Result_, MutableInt>> propertyToItemCountMap,
22+
private State(boolean isMin, NavigableMap<Property_, Map<Result_, MutableInt>> propertyToItemCountMap,
2123
Function<? super Result_, ? extends Property_> propertyFunction) {
2224
this.isMin = isMin;
2325
this.propertyToItemCountMap = propertyToItemCountMap;
@@ -64,10 +66,10 @@ public static <Result, Property extends Comparable<? super Property>> State<Resu
6466
}
6567

6668
private final State<Result_, Property_> state;
67-
private Result_ cachedItem;
68-
private Property_ cachedKey;
69-
private Map<Result_, MutableInt> cachedInnerMap;
70-
private MutableInt cachedCount;
69+
private @Nullable Result_ cachedItem;
70+
private @Nullable Property_ cachedKey;
71+
private @Nullable Map<Result_, MutableInt> cachedInnerMap;
72+
private @Nullable MutableInt cachedCount;
7173

7274
public AbstractMinMaxSlot(State<Result_, Property_> state) {
7375
this.state = state;

core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/AbstractReferenceAverageSlot.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@
88
import java.util.function.BinaryOperator;
99
import java.util.function.Supplier;
1010

11+
import org.jspecify.annotations.Nullable;
12+
1113
public abstract class AbstractReferenceAverageSlot<Input_, Output_> {
1214

1315
public static final class State<Input_, Output_> {
14-
int count = 0;
15-
Input_ sum;
16+
private int count = 0;
17+
private Input_ sum;
1618
final BinaryOperator<Input_> adder;
1719
final BinaryOperator<Input_> subtractor;
1820
final BiFunction<Input_, Integer, Output_> divider;
@@ -34,7 +36,7 @@ public Output_ result() {
3436
}
3537

3638
private final State<Input_, Output_> state;
37-
private Input_ cachedValue;
39+
private @Nullable Input_ cachedValue;
3840

3941
private final static Supplier<State<BigDecimal, BigDecimal>> BIG_DECIMAL =
4042
() -> new State<>(BigDecimal.ZERO, BigDecimal::add, BigDecimal::subtract,

core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/AbstractReferenceSumSlot.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22

33
import java.util.function.BinaryOperator;
44

5+
import org.jspecify.annotations.Nullable;
6+
57
public abstract class AbstractReferenceSumSlot<Result_> {
68

79
public static final class State<Result_> {
8-
Result_ current;
9-
final BinaryOperator<Result_> adder;
10-
final BinaryOperator<Result_> subtractor;
10+
private Result_ current;
11+
private final BinaryOperator<Result_> adder;
12+
private final BinaryOperator<Result_> subtractor;
1113

1214
public State(Result_ zero, BinaryOperator<Result_> adder, BinaryOperator<Result_> subtractor) {
1315
this.current = zero;
@@ -21,7 +23,7 @@ public Result_ result() {
2123
}
2224

2325
private final State<Result_> state;
24-
private Result_ cachedValue;
26+
private @Nullable Result_ cachedValue;
2527

2628
public AbstractReferenceSumSlot(State<Result_> state) {
2729
this.state = state;

core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/AbstractSequenceSlot.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import ai.timefold.solver.core.api.score.stream.common.SequenceChain;
88
import ai.timefold.solver.core.impl.score.stream.collector.consecutive.ConsecutiveSetTree;
99

10+
import org.jspecify.annotations.Nullable;
11+
1012
public abstract class AbstractSequenceSlot<Result_> {
1113

1214
public static final class State<Result_> {
@@ -25,7 +27,7 @@ public SequenceChain<Result_, Integer> result() {
2527
}
2628

2729
private final State<Result_> state;
28-
private Result_ cachedValue;
30+
private @Nullable Result_ cachedValue;
2931

3032
public AbstractSequenceSlot(State<Result_> state) {
3133
this.state = state;

core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/AbstractSortedSetSlot.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88

99
import ai.timefold.solver.core.impl.util.MutableInt;
1010

11+
import org.jspecify.annotations.Nullable;
12+
1113
public abstract class AbstractSortedSetSlot<Mapped_> {
1214
public static final class State<Mapped_> {
13-
final NavigableMap<Mapped_, MutableInt> itemToCount;
15+
private final NavigableMap<Mapped_, MutableInt> itemToCount;
1416

1517
public State(Comparator<? super Mapped_> comparator) {
1618
this.itemToCount = new TreeMap<>(comparator);
@@ -22,8 +24,8 @@ public NavigableSet<Mapped_> result() {
2224
}
2325

2426
private final State<Mapped_> state;
25-
private Mapped_ cachedValue;
26-
private MutableInt cachedCount;
27+
private @Nullable Mapped_ cachedValue;
28+
private @Nullable MutableInt cachedCount;
2729

2830
public AbstractSortedSetSlot(State<Mapped_> state) {
2931
this.state = state;

0 commit comments

Comments
 (0)