Skip to content

Commit 3bf5d40

Browse files
authored
perf: improve tuple store performance (#1329)
We were being too clever and the clever approach doesn't seem justified. This improves performance in the benchmarks by 3 to 6 percent.
1 parent 39b7ab6 commit 3bf5d40

File tree

2 files changed

+14
-32
lines changed

2 files changed

+14
-32
lines changed

core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/common/AbstractJoinNode.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ private void updateOutTupleLeft(OutTuple_ outTuple, LeftTuple_ leftTuple) {
9191
private void doUpdateOutTuple(OutTuple_ outTuple) {
9292
var state = outTuple.state;
9393
if (!state.isActive()) { // Impossible because they shouldn't linger in the indexes.
94-
throw new IllegalStateException("Impossible state: The tuple (" + outTuple.state + ") in node (" +
95-
this + ") is in an unexpected state (" + outTuple.state + ").");
94+
throw new IllegalStateException("Impossible state: The tuple (%s) in node (%s) is in an unexpected state (%s)."
95+
.formatted(outTuple, this, outTuple.state));
9696
} else if (state != TupleState.OK) { // Already in the queue in the correct state.
9797
return;
9898
}
@@ -155,10 +155,9 @@ protected final void retractOutTuple(OutTuple_ outTuple) {
155155
ElementAwareListEntry<OutTuple_> outEntryRight = outTuple.removeStore(outputStoreIndexRightOutEntry);
156156
outEntryRight.remove();
157157
var state = outTuple.state;
158-
if (!state.isActive()) {
159-
// Impossible because they shouldn't linger in the indexes.
160-
throw new IllegalStateException("Impossible state: The tuple (" + outTuple.state + ") in node (" + this
161-
+ ") is in an unexpected state (" + outTuple.state + ").");
158+
if (!state.isActive()) { // Impossible because they shouldn't linger in the indexes.
159+
throw new IllegalStateException("Impossible state: The tuple (%s) in node (%s) is in an unexpected state (%s)."
160+
.formatted(outTuple, this, outTuple.state));
162161
}
163162
propagationQueue.retract(outTuple, state == TupleState.CREATING ? TupleState.ABORTING : TupleState.DYING);
164163
}

core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/common/tuple/AbstractTuple.java

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,43 +19,26 @@
1919
*/
2020
public abstract sealed class AbstractTuple permits UniTuple, BiTuple, TriTuple, QuadTuple {
2121

22-
/*
23-
* We create a lot of tuples, many of them having store size of 1.
24-
* If an array of size 1 was created for each such tuple, memory would be wasted and indirection created.
25-
* This trade-off of increased memory efficiency for marginally slower access time is proven beneficial.
26-
*/
27-
private final boolean storeIsArray;
28-
29-
private Object store;
22+
private static final Object[] EMPTY_STORE = new Object[0];
23+
24+
private final Object[] store;
3025
public TupleState state = TupleState.DEAD; // It's the node's job to mark a new tuple as CREATING.
3126

3227
protected AbstractTuple(int storeSize) {
33-
this.store = (storeSize < 2) ? null : new Object[storeSize];
34-
this.storeIsArray = store != null;
28+
this.store = storeSize == 0 ? EMPTY_STORE : new Object[storeSize];
3529
}
3630

3731
public final <Value_> Value_ getStore(int index) {
38-
return (Value_) (storeIsArray ? ((Object[]) store)[index] : store);
32+
return (Value_) store[index];
3933
}
4034

4135
public final void setStore(int index, Object value) {
42-
if (storeIsArray) {
43-
((Object[]) store)[index] = value;
44-
} else {
45-
store = value;
46-
}
36+
store[index] = value;
4737
}
4838

49-
public <Value_> Value_ removeStore(int index) {
50-
Value_ value;
51-
if (storeIsArray) {
52-
Object[] array = (Object[]) store;
53-
value = (Value_) array[index];
54-
array[index] = null;
55-
} else {
56-
value = (Value_) store;
57-
store = null;
58-
}
39+
public final <Value_> Value_ removeStore(int index) {
40+
Value_ value = getStore(index);
41+
setStore(index, null);
5942
return value;
6043
}
6144

0 commit comments

Comments
 (0)