Repository: hbase
Updated Branches:
  refs/heads/branch-1.2 8273dfad5 -> ff29edc85
  refs/heads/branch-1.3 10e486882 -> 9321f7d86
  refs/heads/branch-1.4 f1f97ff02 -> 8a7ff12c5


HBASE-21228 Memory leak since AbstractFSWAL caches Thread object and never 
clean later


Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/8a7ff12c
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/8a7ff12c
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/8a7ff12c

Branch: refs/heads/branch-1.4
Commit: 8a7ff12c558611ec740a08eaa6008801f9b4ed5d
Parents: f1f97ff
Author: Allan Yang <allan...@apache.org>
Authored: Thu Sep 27 16:44:46 2018 +0800
Committer: Andrew Purtell <apurt...@apache.org>
Committed: Thu Sep 27 17:51:33 2018 -0700

----------------------------------------------------------------------
 .../hadoop/hbase/regionserver/wal/FSHLog.java   | 26 +++++++++-----------
 1 file changed, 12 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/8a7ff12c/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/wal/FSHLog.java
----------------------------------------------------------------------
diff --git 
a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/wal/FSHLog.java
 
b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/wal/FSHLog.java
index 593132f..2ccfcae 100644
--- 
a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/wal/FSHLog.java
+++ 
b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/wal/FSHLog.java
@@ -188,12 +188,11 @@ public class FSHLog implements WAL {
   private final RingBufferEventHandler ringBufferEventHandler;
 
   /**
-   * Map of {@link SyncFuture}s keyed by Handler objects.  Used so we reuse 
SyncFutures.
-   * TODO: Reus FSWALEntry's rather than create them anew each time as we do 
SyncFutures here.
-   * TODO: Add a FSWalEntry and SyncFuture as thread locals on handlers rather 
than have them
-   * get them from this Map?
+   * Map of {@link SyncFuture}s owned by Thread objects. Used so we reuse 
SyncFutures.
+   * Thread local is used so JVM can GC the terminated thread for us. See 
HBASE-21228
+   * <p>
    */
-  private final Map<Thread, SyncFuture> syncFuturesByHandler;
+  private final ThreadLocal<SyncFuture> cachedSyncFutures;
 
   /**
    * The highest known outstanding unsync'd WALEdit sequence number where 
sequence number is the
@@ -567,8 +566,12 @@ public class FSHLog implements WAL {
         maxHandlersCount);
     this.disruptor.handleExceptionsWith(new RingBufferExceptionHandler());
     this.disruptor.handleEventsWith(new RingBufferEventHandler [] 
{this.ringBufferEventHandler});
-    // Presize our map of SyncFutures by handler objects.
-    this.syncFuturesByHandler = new ConcurrentHashMap<Thread, 
SyncFuture>(maxHandlersCount);
+    this.cachedSyncFutures = new ThreadLocal<SyncFuture>() {
+      @Override
+      protected SyncFuture initialValue() {
+        return new SyncFuture();
+      }
+    };
     // Starting up threads in constructor is a no no; Interface should have an 
init call.
     this.disruptor.start();
   }
@@ -1420,7 +1423,7 @@ public class FSHLog implements WAL {
       // SyncFuture reuse by thread, if TimeoutIOException happens, ringbuffer
       // still refer to it, so if this thread use it next time may get a wrong
       // result.
-      this.syncFuturesByHandler.remove(Thread.currentThread());
+      this.cachedSyncFutures.remove();
       throw tioe;
     } catch (InterruptedException ie) {
       LOG.warn("Interrupted", ie);
@@ -1438,12 +1441,7 @@ public class FSHLog implements WAL {
   }
 
   private SyncFuture getSyncFuture(final long sequence, Span span) {
-    SyncFuture syncFuture = 
this.syncFuturesByHandler.get(Thread.currentThread());
-    if (syncFuture == null) {
-      syncFuture = new SyncFuture();
-      this.syncFuturesByHandler.put(Thread.currentThread(), syncFuture);
-    }
-    return syncFuture.reset(sequence, span);
+    return cachedSyncFutures.get().reset(sequence);
   }
 
   private void postSync(final long timeInNanos, final int handlerSyncs) {

Reply via email to