Skip to content

Commit c06c5cc

Browse files
committed
Replace multiplication with shift
Since the multiplier is a power-of-two, we should avoid relying on the compiler noticing that and perform the optimization directly. Of course, the JIT does realize this in C2, but ideally we don't write code making those assumptions as easy to regress.
1 parent 2ce49a4 commit c06c5cc

File tree

2 files changed

+8
-1
lines changed

2 files changed

+8
-1
lines changed

caffeine/src/jmh/java/com/github/benmanes/caffeine/cache/TimerWheelBenchmark.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ public void expire(ThreadState threadState) {
8080
timerWheel.schedule(timer);
8181
}
8282

83+
@Benchmark
84+
public long getExpirationDelay() {
85+
return timerWheel.getExpirationDelay();
86+
}
87+
8388
static final class Timer extends Node<Integer, Integer> {
8489
Node<Integer, Integer> prev;
8590
Node<Integer, Integer> next;

caffeine/src/main/java/com/github/benmanes/caffeine/cache/TimerWheel.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ void unlink(Node<K, V> node) {
234234
}
235235

236236
/** Returns the duration until the next bucket expires, or {@link Long.MAX_VALUE} if none. */
237+
@SuppressWarnings("IntLongMath")
237238
public long getExpirationDelay() {
238239
for (int i = 0; i < SHIFT.length; i++) {
239240
Node<K, V>[] timerWheel = wheel[i];
@@ -247,7 +248,8 @@ public long getExpirationDelay() {
247248
Node<K, V> sentinel = timerWheel[(j & mask)];
248249
Node<K, V> next = sentinel.getNextInVariableOrder();
249250
if (sentinel != next) {
250-
long delay = ((j - start) * SPANS[i]) - (nanos & spanMask);
251+
long buckets = (j - start);
252+
long delay = (buckets << SHIFT[i]) - (nanos & spanMask);
251253
return (delay > 0) ? delay : SPANS[i];
252254
}
253255
}

0 commit comments

Comments
 (0)