You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by je...@apache.org on 2021/11/30 13:14:52 UTC

[geode] branch develop updated: GEODE-9669: Improve reporting of Radish mem_fragmentation_ratio (#7127)

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

jensdeppe pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git


The following commit(s) were added to refs/heads/develop by this push:
     new e69590e  GEODE-9669: Improve reporting of Radish mem_fragmentation_ratio (#7127)
e69590e is described below

commit e69590e1061c0184385c1b2305f7593b1ec3f01a
Author: Jens Deppe <jd...@vmware.com>
AuthorDate: Tue Nov 30 05:13:35 2021 -0800

    GEODE-9669: Improve reporting of Radish mem_fragmentation_ratio (#7127)
    
    - For this implementation, this value is the ratio of total amount of
      memory available to the JVM (Java heap) vs. the amount of memory
      used by the JVM.
---
 .../AbstractRedisInfoStatsIntegrationTest.java     |  2 --
 .../AbstractAppendMemoryIntegrationTest.java       | 16 +++++----
 .../commands/executor/server/InfoExecutor.java     | 38 +++++++++++++++++-----
 3 files changed, 40 insertions(+), 16 deletions(-)

diff --git a/geode-for-redis/src/integrationTest/java/org/apache/geode/redis/internal/commands/executor/server/AbstractRedisInfoStatsIntegrationTest.java b/geode-for-redis/src/integrationTest/java/org/apache/geode/redis/internal/commands/executor/server/AbstractRedisInfoStatsIntegrationTest.java
index 480619f..30c1edc 100644
--- a/geode-for-redis/src/integrationTest/java/org/apache/geode/redis/internal/commands/executor/server/AbstractRedisInfoStatsIntegrationTest.java
+++ b/geode-for-redis/src/integrationTest/java/org/apache/geode/redis/internal/commands/executor/server/AbstractRedisInfoStatsIntegrationTest.java
@@ -28,7 +28,6 @@ import org.assertj.core.data.Offset;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.BeforeClass;
-import org.junit.Ignore;
 import org.junit.Test;
 import redis.clients.jedis.Jedis;
 
@@ -142,7 +141,6 @@ public abstract class AbstractRedisInfoStatsIntegrationTest implements RedisInte
     assertThat(Long.valueOf(getInfo(jedis).get(USED_MEMORY))).isGreaterThan(0);
   }
 
-  @Ignore("tracked by GEODE-9669") // currently we return 1.0
   @Test
   public void memFragmentation_shouldBeGreaterThanOne() {
     for (int i = 0; i < 10000; i++) {
diff --git a/geode-for-redis/src/integrationTest/java/org/apache/geode/redis/internal/commands/executor/string/AbstractAppendMemoryIntegrationTest.java b/geode-for-redis/src/integrationTest/java/org/apache/geode/redis/internal/commands/executor/string/AbstractAppendMemoryIntegrationTest.java
index 05bea0b..e1e44e9 100644
--- a/geode-for-redis/src/integrationTest/java/org/apache/geode/redis/internal/commands/executor/string/AbstractAppendMemoryIntegrationTest.java
+++ b/geode-for-redis/src/integrationTest/java/org/apache/geode/redis/internal/commands/executor/string/AbstractAppendMemoryIntegrationTest.java
@@ -16,6 +16,7 @@ package org.apache.geode.redis.internal.commands.executor.string;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
+import java.time.Duration;
 import java.util.Map;
 
 import org.junit.After;
@@ -45,21 +46,24 @@ public abstract class AbstractAppendMemoryIntegrationTest implements RedisIntegr
 
   @Test
   public void testAppend_actuallyIncreasesBucketSize() {
-    int listSize = 1000;
+    int listSize = 100_000;
     String key = "key";
 
-    Map<String, String> info = RedisTestHelper.getInfo(jedis);
-    Long previousMemValue = Long.valueOf(info.get("used_memory"));
+    System.gc();
+    Long startingMemValue = getUsedMemory(jedis);
 
     jedis.set(key, "initial");
     for (int i = 0; i < listSize; i++) {
       jedis.append(key, "morestuff");
     }
 
-    info = RedisTestHelper.getInfo(jedis);
-    Long finalMemValue = Long.valueOf(info.get("used_memory"));
+    GeodeAwaitility.await().atMost(Duration.ofSeconds(20)).pollInterval(Duration.ofSeconds(1))
+        .untilAsserted(() -> assertThat(getUsedMemory(jedis)).isGreaterThan(startingMemValue));
+  }
 
-    assertThat(finalMemValue).isGreaterThan(previousMemValue);
+  private Long getUsedMemory(Jedis jedis) {
+    Map<String, String> info = RedisTestHelper.getInfo(jedis);
+    return Long.valueOf(info.get("used_memory"));
   }
 
 }
diff --git a/geode-for-redis/src/main/java/org/apache/geode/redis/internal/commands/executor/server/InfoExecutor.java b/geode-for-redis/src/main/java/org/apache/geode/redis/internal/commands/executor/server/InfoExecutor.java
index 2a3c420..08192df 100644
--- a/geode-for-redis/src/main/java/org/apache/geode/redis/internal/commands/executor/server/InfoExecutor.java
+++ b/geode-for-redis/src/main/java/org/apache/geode/redis/internal/commands/executor/server/InfoExecutor.java
@@ -31,7 +31,6 @@ import java.text.DecimalFormat;
 import java.util.Arrays;
 import java.util.List;
 
-import org.apache.geode.internal.cache.PartitionedRegion;
 import org.apache.geode.redis.internal.commands.Command;
 import org.apache.geode.redis.internal.commands.executor.CommandExecutor;
 import org.apache.geode.redis.internal.commands.executor.RedisResponse;
@@ -77,7 +76,7 @@ public class InfoExecutor implements CommandExecutor {
     } else if (Arrays.equals(bytes, CLIENTS)) {
       return getClientsSection(context);
     } else if (Arrays.equals(bytes, MEMORY)) {
-      return getMemorySection(context);
+      return getMemorySection();
     } else if (Arrays.equals(bytes, KEYSPACE)) {
       return getKeyspaceSection(context);
     } else if (Arrays.equals(bytes, DEFAULT) || Arrays.equals(bytes, ALL)) {
@@ -127,13 +126,36 @@ public class InfoExecutor implements CommandExecutor {
         "blocked_clients:0\r\n";
   }
 
-  private String getMemorySection(ExecutionHandlerContext context) {
-    PartitionedRegion pr = (PartitionedRegion) context.getRegionProvider().getDataRegion();
-    long usedMemory = pr.getDataStore().currentAllocatedMemory();
+  /**
+   * Redis' fragmentation ratio is calculated from process_rss / used_memory. Essentially this is
+   * the ratio of physical memory being used vs. the amount of virtual memory the process
+   * requires. So, effectively an indication of memory pressure. If this number goes below 1.0 it
+   * would indicate that the process has started to swap memory which is bad.
+   * <p/>
+   * In a similar sense, the calculation for fragmentation here is a ratio of the maximum amount
+   * of memory available to the JVM (Java heap) vs. the amount of memory used by the JVM. This
+   * ratio can only approach 1.0 and cannot go lower. However, the closer to 1.0, the greater the
+   * likelihood of incurring GC pauses. This is analogous to swapping and will have a very
+   * similar effect in that it will adversely impact performance.
+   * <p/>
+   * Used memory is derived from {@link Runtime} memory and is calculated as
+   * {@code totalMemory() - freeMemory()}.
+   */
+  private String getMemorySection() {
+    long usedMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
+
+    String fragmentationRatio;
+    if (usedMemory != 0) {
+      fragmentationRatio = String.format("%.2f",
+          Runtime.getRuntime().maxMemory() / (float) usedMemory);
+    } else {
+      fragmentationRatio = "1.0";
+    }
+
     return "# Memory\r\n" +
-        "maxmemory:" + pr.getLocalMaxMemory() * ONE_MEGABYTE + "\r\n" +
+        "maxmemory:" + Runtime.getRuntime().maxMemory() + "\r\n" +
         "used_memory:" + usedMemory + "\r\n" +
-        "mem_fragmentation_ratio:1.00\r\n";
+        "mem_fragmentation_ratio:" + fragmentationRatio + "\r\n";
   }
 
   private String getKeyspaceSection(ExecutionHandlerContext context) {
@@ -169,7 +191,7 @@ public class InfoExecutor implements CommandExecutor {
     final String SECTION_SEPARATOR = "\r\n";
     return getServerSection(context) + SECTION_SEPARATOR +
         getClientsSection(context) + SECTION_SEPARATOR +
-        getMemorySection(context) + SECTION_SEPARATOR +
+        getMemorySection() + SECTION_SEPARATOR +
         getPersistenceSection() + SECTION_SEPARATOR +
         getStatsSection(context) + SECTION_SEPARATOR +
         getKeyspaceSection(context) + SECTION_SEPARATOR +