You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ib...@apache.org on 2022/09/26 13:49:02 UTC

[ignite] branch master updated: IGNITE-17728 Improve size-related metrics (#10259)

This is an automated email from the ASF dual-hosted git repository.

ibessonov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new d6159f57b60 IGNITE-17728 Improve size-related metrics (#10259)
d6159f57b60 is described below

commit d6159f57b60c340f1053077e5b2bbbe439b688c7
Author: Alexander Polovtcev <al...@gmail.com>
AuthorDate: Mon Sep 26 16:48:45 2022 +0300

    IGNITE-17728 Improve size-related metrics (#10259)
---
 .../java/org/apache/ignite/DataRegionMetrics.java  | 23 +++++---
 .../cache/persistence/DataRegionMetricsImpl.java   | 61 +++++++++++++++----
 .../persistence/DataRegionMetricsMXBeanImpl.java   |  9 ++-
 .../persistence/DataRegionMetricsSnapshot.java     | 59 +++++++++++--------
 .../cache/persistence/pagemem/PageMetricsImpl.java |  1 -
 .../persistence/pagemem/FillFactorMetricTest.java  | 68 ++++++++++------------
 .../Cache/DataRegionMetricsTest.cs                 |  2 +-
 7 files changed, 139 insertions(+), 84 deletions(-)

diff --git a/modules/core/src/main/java/org/apache/ignite/DataRegionMetrics.java b/modules/core/src/main/java/org/apache/ignite/DataRegionMetrics.java
index 58fd5360643..7d6f3c48974 100644
--- a/modules/core/src/main/java/org/apache/ignite/DataRegionMetrics.java
+++ b/modules/core/src/main/java/org/apache/ignite/DataRegionMetrics.java
@@ -75,6 +75,15 @@ public interface DataRegionMetrics {
      */
     public long getTotalAllocatedPages();
 
+    /**
+     * Gets a total size of memory allocated in the data region. When persistence is disabled, this
+     * metric shows the total size of pages in memory. When persistence is enabled, this metric shows the
+     * total size of pages in memory and on disk.
+     *
+     * @return Total size of memory allocated, in bytes.
+     */
+    public long getTotalAllocatedSize();
+
     /**
      * Gets a total number of pages used for storing the data. It includes allocated pages except of empty
      * pages that are not used yet or pages that can be reused.
@@ -88,13 +97,13 @@ public interface DataRegionMetrics {
     public long getTotalUsedPages();
 
     /**
-     * Gets a total size of memory allocated in the data region. When persistence is disabled, this
-     * metric shows the total size of pages in memory. When persistence is enabled, this metric shows the
-     * total size of pages in memory and on disk.
+     * Returns the total amount of bytes occupied by the non-empty pages. This value is directly tied to the
+     * {@link #getTotalUsedPages} and does not take page fragmentation into account (i.e. if some data is removed from
+     * a page, but it is not completely empty, it will still show the whole page bytes as being occupied).
      *
-     * @return Total size of memory allocated, in bytes.
+     * @return Total amount of bytes occupied by the non-empty pages
      */
-    public long getTotalAllocatedSize();
+    public long getTotalUsedSize();
 
     /**
      * Gets pages allocation rate of a memory region.
@@ -119,9 +128,9 @@ public interface DataRegionMetrics {
     public float getLargeEntriesPagesPercentage();
 
     /**
-     * Gets the percentage of the used space.
+     * Returns the ratio of space occupied by user and system data to the whole allocated space.
      *
-     * @return The percentage of the used space.
+     * @return Ratio of space occupied by user and system data to the whole allocated space.
      */
     public float getPagesFillFactor();
 
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataRegionMetricsImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataRegionMetricsImpl.java
index 188ed968874..18e70b72c24 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataRegionMetricsImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataRegionMetricsImpl.java
@@ -168,6 +168,7 @@ public class DataRegionMetricsImpl implements DataRegionMetrics {
     private volatile long rateTimeInterval;
 
     /** Histogram of cold/hot pages. */
+    @Nullable
     private final PeriodicHistogramMetricImpl pageTsHistogram;
 
     /**
@@ -316,14 +317,19 @@ public class DataRegionMetricsImpl implements DataRegionMetrics {
         return dataRegionPageMetrics.totalPages().value();
     }
 
+    /** {@inheritDoc} */
+    @Override public long getTotalAllocatedSize() {
+        return getTotalAllocatedPages() * pageMem.systemPageSize();
+    }
+
     /** {@inheritDoc} */
     @Override public long getTotalUsedPages() {
         return getTotalAllocatedPages() - dataRegionMetricsProvider.emptyDataPages();
     }
 
     /** {@inheritDoc} */
-    @Override public long getTotalAllocatedSize() {
-        return getTotalAllocatedPages() * (persistenceEnabled ? pageMem.pageSize() : pageMem.systemPageSize());
+    @Override public long getTotalUsedSize() {
+        return getTotalUsedPages() * pageMem.systemPageSize();
     }
 
     /** {@inheritDoc} */
@@ -356,11 +362,29 @@ public class DataRegionMetricsImpl implements DataRegionMetrics {
         if (!metricsEnabled)
             return 0;
 
-        long freeSpace = dataRegionMetricsProvider.partiallyFilledPagesFreeSpace();
+        long totalSpace = getTotalAllocatedSize();
+
+        if (totalSpace == 0)
+            return 0;
+
+        return (float)getSizeUsedByData() / totalSpace;
+    }
+
+    /**
+     * Calculates the number of bytes, occupied by data. Unlike {@link #getTotalUsedSize} it also takes into account the
+     * empty space in non-empty pages.
+     */
+    private long getSizeUsedByData() {
+        // Total amount of bytes occupied by all pages.
+        long totalSpace = getTotalAllocatedSize();
+
+        // Amount of free bytes in fragmented data pages.
+        long partiallyFreeSpace = dataRegionMetricsProvider.partiallyFilledPagesFreeSpace();
 
-        long totalAllocated = getPageSize() * getTotalAllocatedPages();
+        // Amount of bytes in empty data pages.
+        long emptySpace = dataRegionMetricsProvider.emptyDataPages() * pageMem.systemPageSize();
 
-        return totalAllocated != 0 ? (float)(totalAllocated - freeSpace) / totalAllocated : 0f;
+        return totalSpace - partiallyFreeSpace - emptySpace;
     }
 
     /** {@inheritDoc} */
@@ -555,14 +579,14 @@ public class DataRegionMetricsImpl implements DataRegionMetrics {
             return pageMetrics;
 
         synchronized (cacheGrpMetricsLock) {
-            IntMap<PageMetrics> localCacheGrpMetrics = cacheGrpMetrics;
+            IntMap<PageMetrics> locCacheGrpMetrics = cacheGrpMetrics;
 
             // double check
-            PageMetrics doubleCheckPageMetrics = localCacheGrpMetrics.get(cacheGrpId);
+            PageMetrics doubleCheckPageMetrics = locCacheGrpMetrics.get(cacheGrpId);
             if (doubleCheckPageMetrics != null)
                 return doubleCheckPageMetrics;
 
-            IntMap<PageMetrics> copy = new IntHashMap<>(localCacheGrpMetrics);
+            IntMap<PageMetrics> copy = new IntHashMap<>(locCacheGrpMetrics);
 
             PageMetrics newMetrics = Optional.of(kernalCtx)
                 // both cache and group descriptor can be null
@@ -675,20 +699,35 @@ public class DataRegionMetricsImpl implements DataRegionMetrics {
 
         mreg.register("PagesFillFactor",
             this::getPagesFillFactor,
-            "The percentage of the used space.");
+            "Returns the ratio of space occupied by user and system data to the whole allocated space");
+
+        mreg.register("SizeUsedByData",
+            this::getSizeUsedByData,
+            "Returns the number of bytes, occupied by data. Similar to TotalUsedSize, but it also takes into " +
+                "account the empty space in non-empty pages");
 
         mreg.register("PhysicalMemoryPages",
             this::getPhysicalMemoryPages,
-            "Number of pages residing in physical RAM.");
+            "Number of pages residing in physical RAM");
 
         mreg.register("OffheapUsedSize",
             this::getOffheapUsedSize,
-            "Offheap used size in bytes.");
+            "Offheap used size in bytes");
+
+        // TotalAllocatedPages metrics is registered by PageMetrics
 
         mreg.register("TotalAllocatedSize",
             this::getTotalAllocatedSize,
             "Gets a total size of memory allocated in the data region, in bytes");
 
+        mreg.register("TotalUsedPages",
+            this::getTotalUsedPages,
+            "Gets an amount of non-empty pages allocated in the data region");
+
+        mreg.register("TotalUsedSize",
+            this::getTotalUsedSize,
+            "Gets an amount of bytes, occupied by non-empty pages allocated in the data region");
+
         mreg.register("PhysicalMemorySize",
             this::getPhysicalMemorySize,
             "Gets total size of pages loaded to the RAM, in bytes");
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataRegionMetricsMXBeanImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataRegionMetricsMXBeanImpl.java
index b0e94d88a6b..e68438b1337 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataRegionMetricsMXBeanImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataRegionMetricsMXBeanImpl.java
@@ -75,14 +75,19 @@ class DataRegionMetricsMXBeanImpl implements DataRegionMetricsMXBean {
         return memMetrics.getTotalAllocatedPages();
     }
 
+    /** {@inheritDoc} */
+    @Override public long getTotalAllocatedSize() {
+        return memMetrics.getTotalAllocatedSize();
+    }
+
     /** {@inheritDoc} */
     @Override public long getTotalUsedPages() {
         return memMetrics.getTotalUsedPages();
     }
 
     /** {@inheritDoc} */
-    @Override public long getTotalAllocatedSize() {
-        return memMetrics.getTotalAllocatedSize();
+    @Override public long getTotalUsedSize() {
+        return memMetrics.getTotalUsedSize();
     }
 
     /** {@inheritDoc} */
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataRegionMetricsSnapshot.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataRegionMetricsSnapshot.java
index d18219217d4..316f98fe875 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataRegionMetricsSnapshot.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataRegionMetricsSnapshot.java
@@ -24,70 +24,73 @@ import org.apache.ignite.DataRegionMetrics;
  */
 public class DataRegionMetricsSnapshot implements DataRegionMetrics {
     /** */
-    private String name;
+    private final String name;
 
     /** */
-    private long totalAllocatedPages;
+    private final long totalAllocatedPages;
 
     /** */
-    private long totalUsedPages;
+    private final long totalAllocatedSize;
 
     /** */
-    private long totalAllocatedSize;
+    private final long totalUsedPages;
 
     /** */
-    private float allocationRate;
+    private final long totalUsedSize;
 
     /** */
-    private float evictionRate;
+    private final float allocationRate;
 
     /** */
-    private float largeEntriesPagesPercentage;
+    private final float evictionRate;
 
     /** */
-    private float pagesFillFactor;
+    private final float largeEntriesPagesPercentage;
 
     /** */
-    private long dirtyPages;
+    private final float pagesFillFactor;
 
     /** */
-    private float pageReplaceRate;
+    private final long dirtyPages;
 
     /** */
-    private float pageReplaceAge;
+    private final float pageReplaceRate;
 
     /** */
-    private long physicalMemoryPages;
+    private final float pageReplaceAge;
 
     /** */
-    private long physicalMemorySize;
+    private final long physicalMemoryPages;
 
     /** */
-    private long usedCheckpointBufferPages;
+    private final long physicalMemorySize;
 
     /** */
-    private long usedCheckpointBufferSize;
+    private final long usedCheckpointBufferPages;
 
     /** */
-    private long checkpointBufferSize;
+    private final long usedCheckpointBufferSize;
 
     /** */
-    private int pageSize;
+    private final long checkpointBufferSize;
 
     /** */
-    private long readPages;
+    private final int pageSize;
 
     /** */
-    private long writtenPages;
+    private final long readPages;
 
     /** */
-    private long replacedPage;
+    private final long writtenPages;
 
     /** */
-    private long offHeapSize;
+    private final long replacedPage;
 
     /** */
-    private long offHeapUsedSize;
+    private final long offHeapSize;
+
+    /** */
+    private final long offHeapUsedSize;
 
     /**
      * @param metrics Metrics instance to take a copy.
@@ -95,8 +98,9 @@ public class DataRegionMetricsSnapshot implements DataRegionMetrics {
     public DataRegionMetricsSnapshot(DataRegionMetrics metrics) {
         name = metrics.getName();
         totalAllocatedPages = metrics.getTotalAllocatedPages();
-        totalUsedPages = metrics.getTotalUsedPages();
         totalAllocatedSize = metrics.getTotalAllocatedSize();
+        totalUsedPages = metrics.getTotalUsedPages();
+        totalUsedSize = metrics.getTotalUsedSize();
         allocationRate = metrics.getAllocationRate();
         evictionRate = metrics.getEvictionRate();
         largeEntriesPagesPercentage = metrics.getLargeEntriesPagesPercentage();
@@ -127,14 +131,19 @@ public class DataRegionMetricsSnapshot implements DataRegionMetrics {
         return totalAllocatedPages;
     }
 
+    /** {@inheritDoc} */
+    @Override public long getTotalAllocatedSize() {
+        return totalAllocatedSize;
+    }
+
     /** {@inheritDoc} */
     @Override public long getTotalUsedPages() {
         return totalUsedPages;
     }
 
     /** {@inheritDoc} */
-    @Override public long getTotalAllocatedSize() {
-        return totalAllocatedSize;
+    @Override public long getTotalUsedSize() {
+        return totalUsedSize;
     }
 
     /** {@inheritDoc} */
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMetricsImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMetricsImpl.java
index 84661fbc3ab..3e9b923641b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMetricsImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMetricsImpl.java
@@ -120,7 +120,6 @@ public class PageMetricsImpl implements PageMetrics {
         return totalPages;
     }
 
-
     /** {@inheritDoc} */
     @Override public LongAdderMetric indexPages() {
         return idxPages;
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/FillFactorMetricTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/FillFactorMetricTest.java
index ea4a78643c4..5e424404e47 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/FillFactorMetricTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/FillFactorMetricTest.java
@@ -44,10 +44,10 @@ public class FillFactorMetricTest extends GridCommonAbstractTest {
     private static final String MY_CACHE = "mycache";
 
     /** */
-    public static final int NODES = 2;
+    private static final int NODES = 2;
 
     /** */
-    public static final long LARGE_PRIME = 4294967291L;
+    private static final long LARGE_PRIME = 4294967291L;
 
     /** {@inheritDoc} */
     @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
@@ -78,7 +78,7 @@ public class FillFactorMetricTest extends GridCommonAbstractTest {
     /**
      * Records counter.
      */
-    private AtomicInteger recordsInCache = new AtomicInteger();
+    private final AtomicInteger recordsInCache = new AtomicInteger();
 
     /**
      * Last fill factor values.
@@ -110,16 +110,16 @@ public class FillFactorMetricTest extends GridCommonAbstractTest {
      */
     @Test
     public void testFillAndEmpty() throws Exception {
-        final AtomicBoolean stopLoadFlag = new AtomicBoolean();
-        final AtomicBoolean doneFlag = new AtomicBoolean();
+        AtomicBoolean stopLoadFlag = new AtomicBoolean();
+        AtomicBoolean doneFlag = new AtomicBoolean();
 
         startGrids(NODES);
 
         grid(0).getOrCreateCache(cacheCfg());
 
-        final int pageSize = grid(0).configuration().getDataStorageConfiguration().getPageSize();
+        int pageSize = grid(0).configuration().getDataStorageConfiguration().getPageSize();
 
-        IgniteInternalFuture printStatFut = GridTestUtils.runAsync(new Runnable() {
+        IgniteInternalFuture<?> printStatFut = GridTestUtils.runAsync(new Runnable() {
             @Override public void run() {
                 while (!doneFlag.get()) {
                     log.info("Stat nodes:");
@@ -160,24 +160,22 @@ public class FillFactorMetricTest extends GridCommonAbstractTest {
             stopLoadFlag.set(false);
             recordsInCache.set(0);
 
-            IgniteInternalFuture loadFut = GridTestUtils.runAsync(new Runnable() {
-                @Override public void run() {
-                    IgniteCache<Object, Object> cache = grid(0).cache(MY_CACHE);
+            IgniteInternalFuture<?> loadFut = GridTestUtils.runAsync(() -> {
+                IgniteCache<Object, Object> cache = grid(0).cache(MY_CACHE);
 
-                    while (!stopLoadFlag.get()) {
-                        int i = recordsInCache.incrementAndGet();
+                while (!stopLoadFlag.get()) {
+                    int i = recordsInCache.incrementAndGet();
 
-                        final long res = (i * i) % LARGE_PRIME;
+                    long res = (i * i) % LARGE_PRIME;
 
-                        cache.put(res, new byte[1 << (res % 16)]);
+                    cache.put(res, new byte[1 << (res % 16)]);
 
-                        try {
-                            // Steadily add entries to cache but avoid overconsumption of RAM and CPU
-                            Thread.sleep(1);
-                        }
-                        catch (InterruptedException ie) {
-                            return;
-                        }
+                    try {
+                        // Steadily add entries to cache but avoid overconsumption of RAM and CPU
+                        Thread.sleep(1);
+                    }
+                    catch (InterruptedException ie) {
+                        return;
                     }
                 }
             });
@@ -195,22 +193,20 @@ public class FillFactorMetricTest extends GridCommonAbstractTest {
 
             log.info("Going downward");
 
-            IgniteInternalFuture clearFut = GridTestUtils.runAsync(new Runnable() {
-                @Override public void run() {
-                    IgniteCache<Object, Object> cache = grid(0).cache(MY_CACHE);
+            IgniteInternalFuture<?> clearFut = GridTestUtils.runAsync(() -> {
+                IgniteCache<Object, Object> cache = grid(0).cache(MY_CACHE);
 
-                    int i;
-                    while ((i = recordsInCache.getAndDecrement()) > 0) {
-                        final long res = (i * i) % LARGE_PRIME;
+                int i;
+                while ((i = recordsInCache.getAndDecrement()) > 0) {
+                    long res = (i * i) % LARGE_PRIME;
 
-                        cache.remove(res);
+                    cache.remove(res);
 
-                        try {
-                            Thread.sleep(1);
-                        }
-                        catch (InterruptedException ie) {
-                            return;
-                        }
+                    try {
+                        Thread.sleep(1);
+                    }
+                    catch (InterruptedException ie) {
+                        return;
                     }
                 }
             });
@@ -218,10 +214,8 @@ public class FillFactorMetricTest extends GridCommonAbstractTest {
             // Wait for cache to be cleared
             clearFut.get();
 
-            // Since refactoring of AbstractFreeList with recycling empty data pages,
-            // fill factor after cache cleaning will about 0.99, no more obsolete typically value 0.8
             for (float fillFactor : curFillFactor)
-                assertTrue("FillFactor too low: " + fillFactor, fillFactor > 0.9);
+                assertTrue("FillFactor too low: " + fillFactor, fillFactor > 0.6);
         }
 
         doneFlag.set(true);
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/DataRegionMetricsTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/DataRegionMetricsTest.cs
index 4c26d0ab6ed..6088f206956 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/DataRegionMetricsTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/DataRegionMetricsTest.cs
@@ -147,7 +147,7 @@ namespace Apache.Ignite.Core.Tests.Cache
             Assert.Greater(metrics.TotalAllocatedPages, isPersistent ? 0 : 1000);
             Assert.Greater(metrics.PhysicalMemoryPages, isPersistent ? 0 : 1000);
             Assert.AreEqual(metrics.TotalAllocatedSize,
-                metrics.TotalAllocatedPages * (metrics.PageSize + (isPersistent ? 0 : PageOverhead)));
+                metrics.TotalAllocatedPages * (metrics.PageSize + (isPersistent ? PersistentPageOverhead : PageOverhead)));
             Assert.AreEqual(metrics.PhysicalMemorySize,
                 metrics.PhysicalMemoryPages * (metrics.PageSize + (isPersistent ? PersistentPageOverhead : PageOverhead)));
             Assert.Greater(metrics.OffHeapSize, metrics.PhysicalMemoryPages);