yihleego opened a new issue, #4654:
URL: https://github.com/apache/rocketmq/issues/4654
When starting a broker instance with the default configuration, the
`ScheduleMessageService` will create 180 `DeliverDelayedMessageTimerTask`
objects per second, and 1800 `HandlePutResultTask` objects per second if
`enableAsyncDeliver` is `true`, which is **NOT** good for GC.
Let's see some code:
```java
public class MessageStoreConfig {
// By default, there are 18 levels.
private String messageDelayLevel = "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m
8m 9m 10m 20m 30m 1h 2h";
}
```
[ScheduleMessageService#start](https://github.com/apache/rocketmq/blob/00da3e7249d2339717d96f7ea2ab8e4a2fd4242c/broker/src/main/java/org/apache/rocketmq/broker/schedule/ScheduleMessageService.java#L141)
```java
private static final long FIRST_DELAY_TIME = 1000L;
private static final long DELAY_FOR_A_WHILE = 100L;
private static final long DELAY_FOR_A_PERIOD = 10000L;
private static final long WAIT_FOR_SHUTDOWN = 5000L;
private static final long DELAY_FOR_A_SLEEP = 10L;
public void start() {
if (started.compareAndSet(false, true)) {
// ignore
for (Map.Entry<Integer, Long> entry :
this.delayLevelTable.entrySet()) {
Integer level = entry.getKey();
Long timeDelay = entry.getValue();
Long offset = this.offsetTable.get(level);
if (null == offset) {
offset = 0L;
}
if (timeDelay != null) {
if (this.enableAsyncDeliver) {
// Create a HandlePutResultTask object for each level
if enableAsyncDeliver is true.
this.handleExecutorService.schedule(new
HandlePutResultTask(level), FIRST_DELAY_TIME, TimeUnit.MILLISECONDS);
}
// Create a DeliverDelayedMessageTimerTask object for each
level.
this.deliverExecutorService.schedule(new
DeliverDelayedMessageTimerTask(level, offset), FIRST_DELAY_TIME,
TimeUnit.MILLISECONDS);
}
}
// ignore
}
}
```
[ScheduleMessageService#DeliverDelayedMessageTimerTask](https://github.com/apache/rocketmq/blob/00da3e7249d2339717d96f7ea2ab8e4a2fd4242c/broker/src/main/java/org/apache/rocketmq/broker/schedule/ScheduleMessageService.java#L383)
```java
class DeliverDelayedMessageTimerTask implements Runnable {
@Override
public void run() {
try {
if (isStarted()) {
this.executeOnTimeup();
}
} catch (Exception e) {
// XXX: warn and notify me
log.error("ScheduleMessageService, executeOnTimeup exception",
e);
this.scheduleNextTimerTask(this.offset, DELAY_FOR_A_PERIOD);
}
}
public void executeOnTimeup() {
// ignore
// At the end of execution, a new DeliverDelayedMessageTimerTask
object will be created, and it will run after 100ms.
this.scheduleNextTimerTask(nextOffset, DELAY_FOR_A_WHILE);
}
public void scheduleNextTimerTask(long offset, long delay) {
ScheduleMessageService.this.deliverExecutorService.schedule(new
DeliverDelayedMessageTimerTask(
this.delayLevel, offset), delay, TimeUnit.MILLISECONDS);
}
}
```
[ScheduleMessageService#HandlePutResultTask](https://github.com/apache/rocketmq/blob/00da3e7249d2339717d96f7ea2ab8e4a2fd4242c/broker/src/main/java/org/apache/rocketmq/broker/schedule/ScheduleMessageService.java#L569)
```java
public class HandlePutResultTask implements Runnable {
@Override
public void run() {
// ignore
// At the end of execution, a new HandlePutResultTask object will be
created, and it will run after 10ms.
if (isStarted()) {
ScheduleMessageService.this.handleExecutorService
.schedule(new HandlePutResultTask(this.delayLevel),
DELAY_FOR_A_SLEEP, TimeUnit.MILLISECONDS);
}
}
}
```
---
So, it's better to use `ScheduledExecutorService#scheduleWithFixedDelay`
instead of creating unnecessary objects.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]