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

haonan pushed a commit to branch codex/topprocessmetrics
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit f292ac687a0e2b2a92ec951905f9ced2c0914295
Author: HTHou <[email protected]>
AuthorDate: Wed Apr 15 10:45:18 2026 +0800

    Use resident memory for process metrics across platforms
---
 .../iotdb/db/service/metrics/ProcessMetrics.java   | 115 ++++++++++++++++++++-
 1 file changed, 114 insertions(+), 1 deletion(-)

diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/metrics/ProcessMetrics.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/metrics/ProcessMetrics.java
index 52aed7d54a9..192641dbe49 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/metrics/ProcessMetrics.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/metrics/ProcessMetrics.java
@@ -22,19 +22,38 @@ package org.apache.iotdb.db.service.metrics;
 import org.apache.iotdb.commons.service.metric.enums.Tag;
 import org.apache.iotdb.metrics.AbstractMetricService;
 import org.apache.iotdb.metrics.MetricConstant;
+import org.apache.iotdb.metrics.config.MetricConfig;
+import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
 import org.apache.iotdb.metrics.metricsets.IMetricSet;
 import org.apache.iotdb.metrics.utils.MetricLevel;
 import org.apache.iotdb.metrics.utils.MetricType;
 import org.apache.iotdb.metrics.utils.SystemMetric;
 
 import com.sun.management.OperatingSystemMXBean;
+import com.sun.jna.Library;
+import com.sun.jna.Native;
+import com.sun.jna.Structure;
+import com.sun.jna.platform.win32.BaseTSD.SIZE_T;
+import com.sun.jna.platform.win32.Kernel32;
+import com.sun.jna.platform.win32.WinNT;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
 import java.lang.management.ManagementFactory;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 
 public class ProcessMetrics implements IMetricSet {
+  private static final Logger LOGGER = 
LoggerFactory.getLogger(ProcessMetrics.class);
+  private static final MetricConfig CONFIG = 
MetricConfigDescriptor.getInstance().getMetricConfig();
   private final OperatingSystemMXBean sunOsMxBean;
   private final Runtime runtime;
   private static final String PROCESS = "process";
+  private static final String LINUX_RSS_PREFIX = "VmRSS:";
   private long lastUpdateTime = 0L;
   private volatile long processCpuLoad = 0L;
   private volatile long processCpuTime = 0L;
@@ -213,7 +232,69 @@ public class ProcessMetrics implements IMetricSet {
   }
 
   private long getProcessUsedMemory() {
-    return runtime.totalMemory() - runtime.freeMemory();
+    long residentMemory = getResidentMemory();
+    return residentMemory > 0 ? residentMemory : runtime.totalMemory() - 
runtime.freeMemory();
+  }
+
+  private long getResidentMemory() {
+    if (CONFIG.getPid().isEmpty()) {
+      return 0L;
+    }
+    try {
+      switch (CONFIG.getSystemType()) {
+        case LINUX:
+          return getLinuxResidentMemory();
+        case MAC:
+          return getMacResidentMemory();
+        case WINDOWS:
+          return getWindowsResidentMemory();
+        default:
+          return 0L;
+      }
+    } catch (Exception e) {
+      LOGGER.debug("Failed to get process resident memory for pid {}", 
CONFIG.getPid(), e);
+      return 0L;
+    }
+  }
+
+  private long getLinuxResidentMemory() throws IOException {
+    Path statusPath = Paths.get(String.format("/proc/%s/status", 
CONFIG.getPid()));
+    if (!Files.exists(statusPath)) {
+      return 0L;
+    }
+    for (String line : Files.readAllLines(statusPath)) {
+      if (line.startsWith(LINUX_RSS_PREFIX)) {
+        String[] parts = line.trim().split("\\s+");
+        if (parts.length >= 2) {
+          return Long.parseLong(parts[1]) * 1024L;
+        }
+      }
+    }
+    return 0L;
+  }
+
+  private long getMacResidentMemory() throws IOException, InterruptedException 
{
+    Process process = runtime.exec(new String[] {"ps", "-o", "rss=", "-p", 
CONFIG.getPid()});
+    try (BufferedReader input =
+        new BufferedReader(new InputStreamReader(process.getInputStream()))) {
+      String line = input.readLine();
+      int exitCode = process.waitFor();
+      if (exitCode == 0 && line != null && !line.trim().isEmpty()) {
+        return Long.parseLong(line.trim()) * 1024L;
+      }
+    }
+    return 0L;
+  }
+
+  private long getWindowsResidentMemory() {
+    WinNT.HANDLE hProcess = Kernel32.INSTANCE.GetCurrentProcess();
+    ProcessMemoryCounters counters = new ProcessMemoryCounters();
+    boolean success =
+        PsapiExt.INSTANCE.GetProcessMemoryInfo(hProcess, counters, 
counters.size());
+    if (!success) {
+      return 0L;
+    }
+    return counters.workingSetSize.longValue();
   }
 
   private long getProcessStatus() {
@@ -233,4 +314,36 @@ public class ProcessMetrics implements IMetricSet {
     long totalPhysicalMemorySize = sunOsMxBean.getTotalPhysicalMemorySize();
     return (double) processUsedMemory / (double) totalPhysicalMemorySize * 100;
   }
+
+  public interface PsapiExt extends Library {
+    PsapiExt INSTANCE = Native.load("psapi", PsapiExt.class);
+
+    boolean GetProcessMemoryInfo(
+        WinNT.HANDLE process, ProcessMemoryCounters counters, int size);
+  }
+
+  @Structure.FieldOrder({
+    "cb",
+    "pageFaultCount",
+    "peakWorkingSetSize",
+    "workingSetSize",
+    "quotaPeakPagedPoolUsage",
+    "quotaPagedPoolUsage",
+    "quotaPeakNonPagedPoolUsage",
+    "quotaNonPagedPoolUsage",
+    "pagefileUsage",
+    "peakPagefileUsage"
+  })
+  public static class ProcessMemoryCounters extends Structure {
+    public int cb = size();
+    public int pageFaultCount;
+    public SIZE_T peakWorkingSetSize;
+    public SIZE_T workingSetSize;
+    public SIZE_T quotaPeakPagedPoolUsage;
+    public SIZE_T quotaPagedPoolUsage;
+    public SIZE_T quotaPeakNonPagedPoolUsage;
+    public SIZE_T quotaNonPagedPoolUsage;
+    public SIZE_T pagefileUsage;
+    public SIZE_T peakPagefileUsage;
+  }
 }

Reply via email to