apache / apache/dubbo

HashedWheelTimer worker thread might have accumulative delay problem

Open
#8,949 10 comments 0 reactions 1 assignee Claimed by @zrlw View on GitHub
type/bug
Dominant language
Java
Stars
41.6k
Forks
26.4k
Avg merge
15h 13m
Merged PRs (30d)
4

Description

### Environment

* Dubbo version: 3.0 / master
1. waitForNextTick想法有点多
```
final long currentTime = System.nanoTime() - startTime;
<== startTime是初始化HashedWheelTimer的时间,currentTime是时间差;
应用程序持续运行时间只要不超过262年,currentTime这个值都不会小于0。
即使System.nanoTime()返回的当前时间超过LONG最大值变成了负数,
它和startTime之间的纳秒时间差只要不超过2^64次方-1,currentTime就不会变成负值。
long sleepTimeMs = (deadline - currentTime + 999999) / 1000000;

if (sleepTimeMs <= 0) {
if (currentTime == Long.MIN_VALUE) {
<== Long.MIN_VALUE是-2^64,
程序要持续运行262年之后才有遇到它的机会;返回负值也有问题,调用waitForNextTick的代码只认返回值大于0的情况。
return -Long.MAX_VALUE;
} else {
return currentTime;
}
}

if (isWindows()) {
sleepTimeMs = sleepTimeMs / 10 * 10;
<== 看起来是想让windows至少等10ms,但是sleepTimeMs不足10ms时变成0也不合适吧
}

try {
Thread.sleep(sleepTimeMs);
}
```
2. HashedWheelTimer的maxPendingTimeouts可以任意设置,但实测sleep时间到了也抢不到cpu,比如:
HashedWheelTimerTest的createTaskTest测试方法在4核windows机器上跑单元测试,多半失败:
```
Thread.sleep(100); 《== 实测发现执行expireTimeouts的线程很少能在1秒内抢到cpu,所以这里的100ms是想当然了
Assertions.assertTrue(timeout.isExpired());

timer.stop();
```
更新:抢不到cpu是因为执行timeout任务BlockTask的线程是worker线程,BlockTask的代码:
```
private static class BlockTask implements TimerTask {
@Override
public void run(Timeout timeout) throws InterruptedException {
System.out.println("thread:" + Thread.currentThread() + " timeout:" + timeout); <== 这个是后来加的
this.wait(); 《== 把执行worker的线程阻塞,其他timeout就得不到及时处理了
}
}
```
3. HashedWheelTimerTest.java断言timeout数量超maxPendingTimeouts有时也失败
```
Assertions.assertThrows(RuntimeException.class,
() -> timer.newTimeout(new BlockTask(), 1, TimeUnit.MILLISECONDS));
```
原因是前面创建的timeout的delay是-1,马上就过期了。

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.