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

danhaywood pushed a commit to branch CAUSEWAY-3886
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit b794e379042db1ab8aa9f4b65aceabf7e7a05b31
Author: Dan Haywood <[email protected]>
AuthorDate: Sun Apr 27 13:26:13 2025 +0100

    ESP-3886 : adds utility to measure metaclass memory usage.
---
 commons/src/main/java/module-info.java             |  2 +
 .../causeway/commons/memory/MemoryUsage.java       | 67 ++++++++++++++++++++++
 2 files changed, 69 insertions(+)

diff --git a/commons/src/main/java/module-info.java 
b/commons/src/main/java/module-info.java
index 4d09aa72aaa..92e4474ad9c 100644
--- a/commons/src/main/java/module-info.java
+++ b/commons/src/main/java/module-info.java
@@ -79,8 +79,10 @@
     requires com.fasterxml.jackson.datatype.jsr310;
     requires com.fasterxml.jackson.dataformat.yaml;
     requires com.fasterxml.jackson.datatype.jdk8;
+    requires java.management;
 
     opens org.apache.causeway.commons.internal.resources to java.xml.bind, 
com.sun.xml.bind; // JUnit test
     opens org.apache.causeway.commons.io to java.xml.bind, com.sun.xml.bind;
+    exports org.apache.causeway.commons.memory;
 
 }
\ No newline at end of file
diff --git 
a/commons/src/main/java/org/apache/causeway/commons/memory/MemoryUsage.java 
b/commons/src/main/java/org/apache/causeway/commons/memory/MemoryUsage.java
new file mode 100644
index 00000000000..005526e6230
--- /dev/null
+++ b/commons/src/main/java/org/apache/causeway/commons/memory/MemoryUsage.java
@@ -0,0 +1,67 @@
+package org.apache.causeway.commons.memory;
+
+import lombok.SneakyThrows;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryPoolMXBean;
+import java.util.concurrent.Callable;
+
+public class MemoryUsage {
+
+    private MemoryUsage(java.lang.management.MemoryUsage usage) {
+        this(usage.getUsed() / 1024);
+    }
+
+    private MemoryUsage(final long usedInKb) {
+        this.usedInKb = usedInKb;
+    }
+
+    final long usedInKb;
+
+    @Override
+    public String toString() {
+        return String.format("%,d KB", usedInKb);
+    }
+
+    public static void measureMetaspace(String desc, final Runnable runnable) {
+        MemoryUsage before = metaspace();
+        try {
+            runnable.run();
+        } finally {
+            MemoryUsage after = metaspace();
+            System.out.printf("%s : %s%n", after.minus(before), desc);
+        }
+    }
+
+    static int indent = 0;
+
+    @SneakyThrows
+    public static <T> T measureMetaspace(final String desc, final Callable<T> 
runnable) {
+        MemoryUsage before = metaspace();
+        try {
+            indent++;
+            return runnable.call();
+        } finally {
+            MemoryUsage after = metaspace();
+            System.out.printf("%s%s : %s%n", spaces(indent), 
after.minus(before), desc);
+            indent--;
+        }
+    }
+
+    private static String spaces(int indent) {
+        return " ".repeat(indent * 2);
+    }
+
+    private MemoryUsage minus(MemoryUsage before) {
+        return new MemoryUsage(this.usedInKb - before.usedInKb);
+    }
+
+    public static MemoryUsage metaspace() {
+        for (MemoryPoolMXBean pool : ManagementFactory.getMemoryPoolMXBeans()) 
{
+            if (pool.getName().contains("Metaspace")) {
+                return new MemoryUsage(pool.getUsage());
+            }
+        }
+        throw new RuntimeException("Metaspace Usage not found");
+    }
+}

Reply via email to