Good performance boost by avoiding hashmaps in the single-target case

This commit is contained in:
Tony Garnock-Jones 2023-10-28 15:37:10 +02:00
parent c79724a098
commit f55fd2c668
1 changed files with 27 additions and 1 deletions

View File

@ -8,7 +8,10 @@ import java.util.logging.Logger;
public class Turn {
private final static AtomicLong nextHandle = new AtomicLong(0);
private final static record SinglePending(Actor ac, List<Consumer<Turn>> actions) {}
private final Actor _actor;
private SinglePending _singlePending = null;
private Map<Actor, List<Consumer<Turn>>> _pending = null;
private boolean _complete = false;
@ -42,13 +45,36 @@ public class Turn {
if (_pending != null) {
_pending.forEach((ac, q) -> ac.execute(() -> Turn.forActor(ac, t -> q.forEach(f -> f.accept(t)))));
_pending = null;
} else if (_singlePending != null) {
var ac = _singlePending.ac();
var q = _singlePending.actions();
_singlePending = null;
ac.execute(() -> Turn.forActor(ac, t -> q.forEach(f -> f.accept(t))));
}
_complete = true;
}
private static LinkedList<Consumer<Turn>> singletonList(Consumer<Turn> action) {
var q = new LinkedList<Consumer<Turn>>();
q.add(action);
return q;
}
private void enqueue(Actor target, Consumer<Turn> action) {
if (_complete) throw new IllegalStateException("Attempt to reuse a committed Turn");
if (_pending == null) _pending = new HashMap<>();
if (_pending == null) {
if (_singlePending == null) {
_singlePending = new SinglePending(target, singletonList(action));
return;
}
if (_singlePending.ac() == target) {
_singlePending.actions().add(action);
return;
}
_pending = new HashMap<>();
_pending.put(_singlePending.ac(), _singlePending.actions());
_singlePending = null;
}
_pending.computeIfAbsent(target, k -> new LinkedList<>()).add(action);
}