IGNITE-8347 Memory leaks on restart Ignite node with enabled persistence at ThreadLocal - Fixes #3891.
Signed-off-by: dpavlov <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/d83f1ec0 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/d83f1ec0 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/d83f1ec0 Branch: refs/heads/ignite-2.5 Commit: d83f1ec0a4d010e57fecc12ffd3d1f8346ded61c Parents: 8401fe6 Author: dpavlov <[email protected]> Authored: Thu May 3 18:26:49 2018 +0300 Committer: Andrey Gura <[email protected]> Committed: Mon May 7 17:22:41 2018 +0300 ---------------------------------------------------------------------- .../persistence/pagemem/DelayedDirtyPageWrite.java | 6 +++--- .../pagemem/DelayedPageReplacementTracker.java | 16 +++++++--------- .../internal/MemoryLeaksOnRestartNodeTest.java | 3 --- 3 files changed, 10 insertions(+), 15 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/d83f1ec0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/DelayedDirtyPageWrite.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/DelayedDirtyPageWrite.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/DelayedDirtyPageWrite.java index 6eec609..b08ddc2 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/DelayedDirtyPageWrite.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/DelayedDirtyPageWrite.java @@ -24,9 +24,9 @@ import org.apache.ignite.internal.util.GridUnsafe; import org.jetbrains.annotations.Nullable; /** - * Not thread safe and stateful class for replacement of one page with write() delay. This allows to write page content - * without holding segment lock. Page data is copied into temp buffer during {@link #writePage(FullPageId, ByteBuffer, - * int)} and then sent to real implementation by {@link #finishReplacement()}. + * Not thread safe and stateful class for page replacement of one page with write() delay. This allows to write page + * content without holding segment lock. Page data is copied into temp buffer during {@link #writePage(FullPageId, + * ByteBuffer, int)} and then sent to real implementation by {@link #finishReplacement()}. */ public class DelayedDirtyPageWrite implements ReplacedPageWriter { /** Real flush dirty page implementation. */ http://git-wip-us.apache.org/repos/asf/ignite/blob/d83f1ec0/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/DelayedPageReplacementTracker.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/DelayedPageReplacementTracker.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/DelayedPageReplacementTracker.java index 9cf5b77..aa1b061 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/DelayedPageReplacementTracker.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/DelayedPageReplacementTracker.java @@ -21,6 +21,8 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Collection; import java.util.HashSet; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import org.apache.ignite.IgniteInterruptedException; import org.apache.ignite.IgniteLogger; import org.apache.ignite.internal.pagemem.FullPageId; @@ -56,15 +58,10 @@ public class DelayedPageReplacementTracker { /** * Dirty page write for replacement operations thread local. Because page write {@link DelayedDirtyPageWrite} is - * stateful and not thread safe, this thread local protects from GC pressure on pages replacement. + * stateful and not thread safe, this thread local protects from GC pressure on pages replacement. <br> Map is used + * instead of build-in thread local to allow GC to remove delayed writers for alive threads after node stop. */ - private final ThreadLocal<DelayedDirtyPageWrite> delayedPageWriteThreadLoc - = new ThreadLocal<DelayedDirtyPageWrite>() { - @Override protected DelayedDirtyPageWrite initialValue() { - return new DelayedDirtyPageWrite(flushDirtyPage, byteBufThreadLoc, pageSize, - DelayedPageReplacementTracker.this); - } - }; + private final Map<Long, DelayedDirtyPageWrite> delayedPageWriteThreadLocMap = new ConcurrentHashMap<>(); /** * @param pageSize Page size. @@ -87,7 +84,8 @@ public class DelayedPageReplacementTracker { * @return delayed page write implementation, finish method to be called to actually write page. */ public DelayedDirtyPageWrite delayedPageWrite() { - return delayedPageWriteThreadLoc.get(); + return delayedPageWriteThreadLocMap.computeIfAbsent(Thread.currentThread().getId(), + id -> new DelayedDirtyPageWrite(flushDirtyPage, byteBufThreadLoc, pageSize, this)); } /** http://git-wip-us.apache.org/repos/asf/ignite/blob/d83f1ec0/modules/core/src/test/java/org/apache/ignite/internal/MemoryLeaksOnRestartNodeTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/MemoryLeaksOnRestartNodeTest.java b/modules/core/src/test/java/org/apache/ignite/internal/MemoryLeaksOnRestartNodeTest.java index 56ab091..df055fe 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/MemoryLeaksOnRestartNodeTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/MemoryLeaksOnRestartNodeTest.java @@ -18,7 +18,6 @@ package org.apache.ignite.internal; import java.io.File; -import org.apache.ignite.IgniteSystemProperties; import org.apache.ignite.configuration.DataRegionConfiguration; import org.apache.ignite.configuration.DataStorageConfiguration; import org.apache.ignite.configuration.IgniteConfiguration; @@ -76,8 +75,6 @@ public class MemoryLeaksOnRestartNodeTest extends GridCommonAbstractTest { * @throws Exception On failed. */ public void test() throws Exception { - System.setProperty(IgniteSystemProperties.IGNITE_DELAYED_REPLACED_PAGE_WRITE, "false"); - // Warmup for (int i = 0; i < RESTARTS / 2; ++i) { startGrids(NODES);
