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

jt2594838 pushed a commit to branch dev/1.3
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/dev/1.3 by this push:
     new 02e190dcfc9 [To dev/1.3] Fix process memory metrics and precision 
(#17482) (#18229) (#18231)
02e190dcfc9 is described below

commit 02e190dcfc994eb28270e2ea4a5265b28eb5d825
Author: Caideyipi <[email protected]>
AuthorDate: Mon Jul 20 09:36:24 2026 +0800

    [To dev/1.3] Fix process memory metrics and precision (#17482) (#18229) 
(#18231)
    
    * Update process memory metrics to report OS resident memory (#17482)
    
    * Use resident memory for process metrics across platforms
    
    * Align process memory metric with top
    
    (cherry picked from commit 5626f1f558ad898562ec9f9f496df48b733b177f)
    
    * Fix process metric precision
    
    (cherry picked from commit f3f580fcb2530aa51c24893e679e073e6a60bb8c)
    
    ---------
    
    Co-authored-by: Haonan <[email protected]>
---
 .../iotdb/db/service/metrics/ProcessMetrics.java   | 121 ++++++++++++++++++++-
 1 file changed, 116 insertions(+), 5 deletions(-)

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..2a4c28a4d35 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,21 +22,40 @@ 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.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 com.sun.management.OperatingSystemMXBean;
+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 double processCpuLoad = 0.0D;
   private volatile long processCpuTime = 0L;
 
   public ProcessMetrics() {
@@ -69,7 +88,7 @@ public class ProcessMetrics implements IMetricSet {
         a -> {
           if (System.currentTimeMillis() - lastUpdateTime > 
MetricConstant.UPDATE_INTERVAL) {
             lastUpdateTime = System.currentTimeMillis();
-            processCpuLoad = (long) (sunOsMxBean.getProcessCpuLoad() * 100);
+            processCpuLoad = sunOsMxBean.getProcessCpuLoad() * 100;
             processCpuTime = sunOsMxBean.getProcessCpuTime();
           }
           return processCpuLoad;
@@ -84,7 +103,7 @@ public class ProcessMetrics implements IMetricSet {
         bean -> {
           if (System.currentTimeMillis() - lastUpdateTime > 
MetricConstant.UPDATE_INTERVAL) {
             lastUpdateTime = System.currentTimeMillis();
-            processCpuLoad = (long) (sunOsMxBean.getProcessCpuLoad() * 100);
+            processCpuLoad = sunOsMxBean.getProcessCpuLoad() * 100;
             processCpuTime = sunOsMxBean.getProcessCpuTime();
           }
           return processCpuTime;
@@ -142,7 +161,7 @@ public class ProcessMetrics implements IMetricSet {
         SystemMetric.PROCESS_MEM_RATIO.toString(),
         MetricLevel.IMPORTANT,
         this,
-        a -> Math.round(getProcessMemoryRatio()),
+        a -> getProcessMemoryRatio(),
         Tag.NAME.toString(),
         PROCESS);
   }
@@ -213,7 +232,68 @@ 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 +313,35 @@ 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