From c06c5cca5c80e578495b206d03c8f76fb74f7b22 Mon Sep 17 00:00:00 2001 From: Ben Manes Date: Sun, 4 Aug 2019 22:21:27 -0700 Subject: [PATCH] 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. --- .../github/benmanes/caffeine/cache/TimerWheelBenchmark.java | 5 +++++ .../java/com/github/benmanes/caffeine/cache/TimerWheel.java | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/caffeine/src/jmh/java/com/github/benmanes/caffeine/cache/TimerWheelBenchmark.java b/caffeine/src/jmh/java/com/github/benmanes/caffeine/cache/TimerWheelBenchmark.java index e0dc2b8ed4..9719800a69 100644 --- a/caffeine/src/jmh/java/com/github/benmanes/caffeine/cache/TimerWheelBenchmark.java +++ b/caffeine/src/jmh/java/com/github/benmanes/caffeine/cache/TimerWheelBenchmark.java @@ -80,6 +80,11 @@ public void expire(ThreadState threadState) { timerWheel.schedule(timer); } + @Benchmark + public long getExpirationDelay() { + return timerWheel.getExpirationDelay(); + } + static final class Timer extends Node { Node prev; Node next; diff --git a/caffeine/src/main/java/com/github/benmanes/caffeine/cache/TimerWheel.java b/caffeine/src/main/java/com/github/benmanes/caffeine/cache/TimerWheel.java index 5c0d09b6dc..5fd35d4289 100644 --- a/caffeine/src/main/java/com/github/benmanes/caffeine/cache/TimerWheel.java +++ b/caffeine/src/main/java/com/github/benmanes/caffeine/cache/TimerWheel.java @@ -234,6 +234,7 @@ void unlink(Node node) { } /** Returns the duration until the next bucket expires, or {@link Long.MAX_VALUE} if none. */ + @SuppressWarnings("IntLongMath") public long getExpirationDelay() { for (int i = 0; i < SHIFT.length; i++) { Node[] timerWheel = wheel[i]; @@ -247,7 +248,8 @@ public long getExpirationDelay() { Node sentinel = timerWheel[(j & mask)]; Node next = sentinel.getNextInVariableOrder(); if (sentinel != next) { - long delay = ((j - start) * SPANS[i]) - (nanos & spanMask); + long buckets = (j - start); + long delay = (buckets << SHIFT[i]) - (nanos & spanMask); return (delay > 0) ? delay : SPANS[i]; } }