LennonChin opened a new pull request, #4435:
URL: https://github.com/apache/hadoop/pull/4435

   ### Description of PR
   
   The DelegationTokenRenewerPoolTracker thread is busy wasting CPU resource in 
empty poll iterate when there is no delegation token renewer event task in the 
futures map:
   
   ```java
   // 
org.apache.hadoop.yarn.server.resourcemanager.security.DelegationTokenRenewer.DelegationTokenRenewerPoolTracker#run
   @Override
   public void run() {
     // this while true loop is busy when the `futures` is empty
     while (true) {
       for (Map.Entry<DelegationTokenRenewerEvent, Future<?>> entry : futures
           .entrySet()) {
         DelegationTokenRenewerEvent evt = entry.getKey();
         Future<?> future = entry.getValue();
         try {
           future.get(tokenRenewerThreadTimeout, TimeUnit.MILLISECONDS);
         } catch (TimeoutException e) {
   
           // Cancel thread and retry the same event in case of timeout
           if (future != null && !future.isDone() && !future.isCancelled()) {
             future.cancel(true);
             futures.remove(evt);
             if (evt.getAttempt() < tokenRenewerThreadRetryMaxAttempts) {
               renewalTimer.schedule(
                   getTimerTask((AbstractDelegationTokenRenewerAppEvent) evt),
                   tokenRenewerThreadRetryInterval);
             } else {
               LOG.info(
                   "Exhausted max retry attempts {} in token renewer "
                       + "thread for {}",
                   tokenRenewerThreadRetryMaxAttempts, evt.getApplicationId());
             }
           }
         } catch (Exception e) {
           LOG.info("Problem in submitting renew tasks in token renewer "
               + "thread.", e);
         }
       }
     }
   }
   ```
   
   A better way to avoid CPU idling is waiting for some time when the `futures` 
map is empty, and when the renewer task done or cancelled, we should remove the 
task future in `futures` map to avoid memory leak:
   
   ```java
   @Override
   public void run() {
     while (true) {
       // waiting for some time when futures map is empty
       if (futures.isEmpty()) {
         synchronized (this) {
           try {
             // waiting for tokenRenewerThreadTimeout milliseconds
             long waitingTimeMs = Math.min(10000, Math.max(500, 
tokenRenewerThreadTimeout));
             LOG.info("Delegation token renewer pool is empty, waiting for {} 
ms.", waitingTimeMs);
             wait(waitingTimeMs);
           } catch (InterruptedException e) {
             LOG.warn("Delegation token renewer pool tracker waiting interrupt 
occurred.");
             Thread.currentThread().interrupt();
           }
         }
         if (futures.isEmpty()) {
           continue;
         }
       }
       for (Map.Entry<DelegationTokenRenewerEvent, Future<?>> entry : futures
           .entrySet()) {
         DelegationTokenRenewerEvent evt = entry.getKey();
         Future<?> future = entry.getValue();
         try {
           future.get(tokenRenewerThreadTimeout, TimeUnit.MILLISECONDS);
         } catch (TimeoutException e) {
   
           // Cancel thread and retry the same event in case of timeout
           if (future != null && !future.isDone() && !future.isCancelled()) {
             future.cancel(true);
             futures.remove(evt);
             if (evt.getAttempt() < tokenRenewerThreadRetryMaxAttempts) {
               renewalTimer.schedule(
                   getTimerTask((AbstractDelegationTokenRenewerAppEvent) evt),
                   tokenRenewerThreadRetryInterval);
             } else {
               LOG.info(
                   "Exhausted max retry attempts {} in token renewer "
                       + "thread for {}",
                   tokenRenewerThreadRetryMaxAttempts, evt.getApplicationId());
             }
           }
         } catch (Exception e) {
           LOG.info("Problem in submitting renew tasks in token renewer "
               + "thread.", e);
         }
         // remove done and cancelled task
         if (future.isDone() || future.isCancelled()) {
           try {
             futures.remove(evt);
             LOG.info("Removed done or cancelled renew tasks of {} in token 
renewer thread.", evt.getApplicationId());
           } catch (Exception e) {
             LOG.warn("Problem in removing done or cancelled renew tasks in 
token renewer thread.", e);
           }
         }
       }
     }
   } 
   ```


-- 
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: common-issues-unsubscr...@hadoop.apache.org

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


---------------------------------------------------------------------
To unsubscribe, e-mail: common-issues-unsubscr...@hadoop.apache.org
For additional commands, e-mail: common-issues-h...@hadoop.apache.org

Reply via email to