Skip to content

Commit fa3938c

Browse files
yangty89mp911de
authored andcommitted
Use HashedWheelTimer for command timeout scheduling to reduce thread context switches and improve performance #2773
Original pull request: #2774
1 parent bb9cd0d commit fa3938c

File tree

1 file changed

+13
-12
lines changed

1 file changed

+13
-12
lines changed

src/main/java/io/lettuce/core/protocol/CommandExpiryWriter.java

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,15 @@
3030
import io.lettuce.core.internal.ExceptionFactory;
3131
import io.lettuce.core.internal.LettuceAssert;
3232
import io.lettuce.core.resource.ClientResources;
33+
import io.netty.util.Timeout;
34+
import io.netty.util.Timer;
3335

3436
/**
3537
* Extension to {@link RedisChannelWriter} that expires commands. Command timeout starts at the time the command is written
3638
* regardless to {@link #setAutoFlushCommands(boolean) flushing mode} (user-controlled batching).
3739
*
3840
* @author Mark Paluch
41+
* @author Tianyi Yang
3942
* @since 5.1
4043
* @see io.lettuce.core.TimeoutOptions
4144
*/
@@ -49,6 +52,8 @@ public class CommandExpiryWriter implements RedisChannelWriter {
4952

5053
private final ScheduledExecutorService executorService;
5154

55+
private final Timer timer;
56+
5257
private final boolean applyConnectionTimeout;
5358

5459
private volatile long timeout = -1;
@@ -72,6 +77,7 @@ public CommandExpiryWriter(RedisChannelWriter delegate, ClientOptions clientOpti
7277
this.applyConnectionTimeout = timeoutOptions.isApplyConnectionTimeout();
7378
this.timeUnit = source.getTimeUnit();
7479
this.executorService = clientResources.eventExecutorGroup();
80+
this.timer = clientResources.timer();
7581
}
7682

7783
/**
@@ -168,24 +174,19 @@ private void potentiallyExpire(RedisCommand<?, ?, ?> command, ScheduledExecutorS
168174
if (timeout <= 0) {
169175
return;
170176
}
171-
172-
ScheduledFuture<?> schedule = executors.schedule(() -> {
173-
177+
178+
Timeout commandTimeout = timer.newTimeout(t -> {
174179
if (!command.isDone()) {
175-
command.completeExceptionally(
176-
ExceptionFactory.createTimeoutException(Duration.ofNanos(timeUnit.toNanos(timeout))));
177-
}
180+
executors.submit(() -> command.completeExceptionally(
181+
ExceptionFactory.createTimeoutException(Duration.ofNanos(timeUnit.toNanos(timeout)))));
178182

183+
}
179184
}, timeout, timeUnit);
180185

181186
if (command instanceof CompleteableCommand) {
182-
((CompleteableCommand) command).onComplete((o, o2) -> {
183-
184-
if (!schedule.isDone()) {
185-
schedule.cancel(false);
186-
}
187-
});
187+
((CompleteableCommand) command).onComplete((o, o2) -> commandTimeout.cancel());
188188
}
189+
189190
}
190191

191192
}

0 commit comments

Comments
 (0)