You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@rocketmq.apache.org by GitBox <gi...@apache.org> on 2022/07/21 11:56:38 UTC

[GitHub] [rocketmq] yihleego opened a new issue, #4654: [OPTIMIZATION] Reduce unnecessary DeliverDelayedMessageTimerTask and HandlePutResultTask object creation

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: dev-unsubscribe@rocketmq.apache.org.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [rocketmq] yihleego closed issue #4654: [OPTIMIZATION] Reduce unnecessary DeliverDelayedMessageTimerTask and HandlePutResultTask object creation

Posted by "yihleego (via GitHub)" <gi...@apache.org>.
yihleego closed issue #4654: [OPTIMIZATION] Reduce unnecessary DeliverDelayedMessageTimerTask and HandlePutResultTask object creation
URL: https://github.com/apache/rocketmq/issues/4654


-- 
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: commits-unsubscribe@rocketmq.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org