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

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


The following commit(s) were added to refs/heads/master by this push:
     new 4757f4d2960 [IOTDB-6198] Pipe: Memory Management Framework (#11350)
4757f4d2960 is described below

commit 4757f4d29602d1404443fa032dc6e18c9d967d17
Author: Itami Sho <[email protected]>
AuthorDate: Wed Oct 25 09:40:19 2023 +0800

    [IOTDB-6198] Pipe: Memory Management Framework (#11350)
    
    Co-authored-by: Steve Yurong Su <[email protected]>
---
 .../java/org/apache/iotdb/db/conf/IoTDBConfig.java | 11 +++
 .../org/apache/iotdb/db/conf/IoTDBDescriptor.java  |  6 ++
 .../db/pipe/resource/PipeResourceManager.java      |  7 ++
 .../db/pipe/resource/memory/PipeMemoryBlock.java   | 50 ++++++++++++
 .../db/pipe/resource/memory/PipeMemoryManager.java | 88 ++++++++++++++++++++++
 .../apache/iotdb/commons/conf/CommonConfig.java    | 19 +++++
 .../iotdb/commons/conf/CommonDescriptor.java       | 12 +++
 .../iotdb/commons/pipe/config/PipeConfig.java      | 14 ++++
 8 files changed, 207 insertions(+)

diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java
index e7685e25c0d..15aa68d6d9f 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java
@@ -145,6 +145,9 @@ public class IoTDBConfig {
   /** Memory allocated for the consensus layer */
   private long allocateMemoryForConsensus = Runtime.getRuntime().maxMemory() / 
10;
 
+  /** Memory allocated for the pipe */
+  private long allocateMemoryForPipe = Runtime.getRuntime().maxMemory() / 10;
+
   /** Ratio of memory allocated for buffered arrays */
   private double bufferedArraysMemoryProportion = 0.6;
 
@@ -1899,6 +1902,14 @@ public class IoTDBConfig {
     this.allocateMemoryForTimeIndex = allocateMemoryForRead * 200 / 1001;
   }
 
+  public long getAllocateMemoryForPipe() {
+    return allocateMemoryForPipe;
+  }
+
+  public void setAllocateMemoryForPipe(long allocateMemoryForPipe) {
+    this.allocateMemoryForPipe = allocateMemoryForPipe;
+  }
+
   public long getAllocateMemoryForFree() {
     return Runtime.getRuntime().maxMemory()
         - allocateMemoryForStorageEngine
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
index 7d0f230bc16..5bf62aa2eee 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
@@ -1712,6 +1712,11 @@ public class IoTDBDescriptor {
             maxMemoryAvailable * Integer.parseInt(proportions[2].trim()) / 
proportionSum);
         conf.setAllocateMemoryForConsensus(
             maxMemoryAvailable * Integer.parseInt(proportions[3].trim()) / 
proportionSum);
+        // if pipe proportion is set, use it, otherwise use the default value
+        if (proportions.length >= 6) {
+          conf.setAllocateMemoryForPipe(
+              maxMemoryAvailable * Integer.parseInt(proportions[4].trim()) / 
proportionSum);
+        }
       }
     }
 
@@ -1719,6 +1724,7 @@ public class IoTDBDescriptor {
     logger.info("initial allocateMemoryForWrite = {}", 
conf.getAllocateMemoryForStorageEngine());
     logger.info("initial allocateMemoryForSchema = {}", 
conf.getAllocateMemoryForSchema());
     logger.info("initial allocateMemoryForConsensus = {}", 
conf.getAllocateMemoryForConsensus());
+    logger.info("initial allocateMemoryForPipe = {}", 
conf.getAllocateMemoryForPipe());
 
     initSchemaMemoryAllocate(properties);
     initStorageEngineAllocate(properties);
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/resource/PipeResourceManager.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/resource/PipeResourceManager.java
index 519aa0b56ab..56fe8cd6bd0 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/resource/PipeResourceManager.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/resource/PipeResourceManager.java
@@ -20,6 +20,7 @@
 package org.apache.iotdb.db.pipe.resource;
 
 import org.apache.iotdb.commons.pipe.config.PipeConfig;
+import org.apache.iotdb.db.pipe.resource.memory.PipeMemoryManager;
 import org.apache.iotdb.db.pipe.resource.tsfile.PipeTsFileResourceManager;
 import org.apache.iotdb.db.pipe.resource.wal.PipeWALResourceManager;
 import 
org.apache.iotdb.db.pipe.resource.wal.hardlink.PipeWALHardlinkResourceManager;
@@ -31,6 +32,7 @@ public class PipeResourceManager {
 
   private final PipeTsFileResourceManager pipeTsFileResourceManager;
   private final AtomicReference<PipeWALResourceManager> pipeWALResourceManager;
+  private final PipeMemoryManager pipeMemoryManager;
 
   public static PipeTsFileResourceManager tsfile() {
     return PipeResourceManagerHolder.INSTANCE.pipeTsFileResourceManager;
@@ -50,11 +52,16 @@ public class PipeResourceManager {
     return PipeResourceManagerHolder.INSTANCE.pipeWALResourceManager.get();
   }
 
+  public static PipeMemoryManager memory() {
+    return PipeResourceManagerHolder.INSTANCE.pipeMemoryManager;
+  }
+
   ///////////////////////////// SINGLETON /////////////////////////////
 
   private PipeResourceManager() {
     pipeTsFileResourceManager = new PipeTsFileResourceManager();
     pipeWALResourceManager = new AtomicReference<>();
+    pipeMemoryManager = new PipeMemoryManager();
   }
 
   private static class PipeResourceManagerHolder {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/resource/memory/PipeMemoryBlock.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/resource/memory/PipeMemoryBlock.java
new file mode 100644
index 00000000000..166f7924b82
--- /dev/null
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/resource/memory/PipeMemoryBlock.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.pipe.resource.memory;
+
+import org.apache.iotdb.db.pipe.resource.PipeResourceManager;
+
+public class PipeMemoryBlock implements AutoCloseable {
+
+  private final long memoryUsageInBytes;
+
+  private volatile boolean isReleased = false;
+
+  public PipeMemoryBlock(long memoryUsageInBytes) {
+    this.memoryUsageInBytes = memoryUsageInBytes;
+  }
+
+  long getMemoryUsageInBytes() {
+    return memoryUsageInBytes;
+  }
+
+  boolean isReleased() {
+    return isReleased;
+  }
+
+  void markAsReleased() {
+    isReleased = true;
+  }
+
+  @Override
+  public void close() throws Exception {
+    PipeResourceManager.memory().release(this);
+  }
+}
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/resource/memory/PipeMemoryManager.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/resource/memory/PipeMemoryManager.java
new file mode 100644
index 00000000000..19a6f80246c
--- /dev/null
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/resource/memory/PipeMemoryManager.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.pipe.resource.memory;
+
+import org.apache.iotdb.commons.exception.pipe.PipeRuntimeCriticalException;
+import org.apache.iotdb.commons.exception.pipe.PipeRuntimeException;
+import org.apache.iotdb.commons.pipe.config.PipeConfig;
+import org.apache.iotdb.db.conf.IoTDBDescriptor;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PipeMemoryManager {
+
+  private static final Logger LOGGER = 
LoggerFactory.getLogger(PipeMemoryManager.class);
+
+  private static final int MEMORY_ALLOCATE_MAX_RETRIES =
+      PipeConfig.getInstance().getPipeMemoryAllocateMaxRetries();
+  private static final long MEMORY_ALLOCATE_RETRY_INTERVAL_IN_MS =
+      PipeConfig.getInstance().getPipeMemoryAllocateRetryIntervalInMs();
+
+  private static final long TOTAL_MEMORY_SIZE_IN_BYTES =
+      IoTDBDescriptor.getInstance().getConfig().getAllocateMemoryForPipe();
+  private long usedMemorySizeInBytes = 0;
+
+  public synchronized PipeMemoryBlock allocate(long sizeInBytes)
+      throws PipeRuntimeException, InterruptedException {
+    for (int i = 1; i <= MEMORY_ALLOCATE_MAX_RETRIES; i++) {
+      if (TOTAL_MEMORY_SIZE_IN_BYTES - usedMemorySizeInBytes >= sizeInBytes) {
+        usedMemorySizeInBytes += sizeInBytes;
+        return new PipeMemoryBlock(sizeInBytes);
+      }
+
+      try {
+        this.wait(MEMORY_ALLOCATE_RETRY_INTERVAL_IN_MS);
+      } catch (InterruptedException e) {
+        Thread.currentThread().interrupt();
+        LOGGER.warn("allocate: interrupted while waiting for available 
memory", e);
+      }
+    }
+
+    throw new PipeRuntimeCriticalException(
+        String.format(
+            "failed to allocate memory after %d retries, "
+                + "total memory size %d bytes, used memory size %d bytes, "
+                + "requested memory size %d bytes",
+            MEMORY_ALLOCATE_MAX_RETRIES,
+            TOTAL_MEMORY_SIZE_IN_BYTES,
+            usedMemorySizeInBytes,
+            sizeInBytes));
+  }
+
+  public synchronized void release(PipeMemoryBlock block) {
+    if (block == null || block.isReleased()) {
+      return;
+    }
+
+    usedMemorySizeInBytes -= block.getMemoryUsageInBytes();
+    block.markAsReleased();
+
+    this.notifyAll();
+  }
+
+  public long getUsedMemorySizeInBytes() {
+    return usedMemorySizeInBytes;
+  }
+
+  public long getTotalMemorySizeInBytes() {
+    return TOTAL_MEMORY_SIZE_IN_BYTES;
+  }
+}
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonConfig.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonConfig.java
index 25c751e83ed..a94c7889a45 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonConfig.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonConfig.java
@@ -191,6 +191,9 @@ public class CommonConfig {
 
   private int pipeMaxAllowedPendingTsFileEpochPerDataRegion = 1;
 
+  private long pipeMemoryAllocateRetryIntervalMs = 1000;
+  private int pipeMemoryAllocateMaxRetries = 10;
+
   /** Whether to use persistent schema mode. */
   private String schemaEngineMode = "Memory";
 
@@ -732,6 +735,22 @@ public class CommonConfig {
     this.pipeMaxAllowedPendingTsFileEpochPerDataRegion = 
pipeExtractorPendingQueueTsfileLimit;
   }
 
+  public int getPipeMemoryAllocateMaxRetries() {
+    return pipeMemoryAllocateMaxRetries;
+  }
+
+  public void setPipeMemoryAllocateMaxRetries(int 
pipeMemoryAllocateMaxRetries) {
+    this.pipeMemoryAllocateMaxRetries = pipeMemoryAllocateMaxRetries;
+  }
+
+  public long getPipeMemoryAllocateRetryIntervalInMs() {
+    return pipeMemoryAllocateRetryIntervalMs;
+  }
+
+  public void setPipeMemoryAllocateRetryIntervalInMs(long 
pipeMemoryAllocateRetryIntervalMs) {
+    this.pipeMemoryAllocateRetryIntervalMs = pipeMemoryAllocateRetryIntervalMs;
+  }
+
   public String getSchemaEngineMode() {
     return schemaEngineMode;
   }
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonDescriptor.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonDescriptor.java
index 047b5a67515..901c67a2da9 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonDescriptor.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonDescriptor.java
@@ -389,6 +389,18 @@ public class CommonDescriptor {
             properties.getProperty(
                 "pipe_max_allowed_pending_tsfile_epoch_per_data_region",
                 
String.valueOf(config.getPipeMaxAllowedPendingTsFileEpochPerDataRegion()))));
+
+    config.setPipeMemoryAllocateMaxRetries(
+        Integer.parseInt(
+            properties.getProperty(
+                "pipe_memory_allocate_max_retries",
+                String.valueOf(config.getPipeMemoryAllocateMaxRetries()))));
+
+    config.setPipeMemoryAllocateRetryIntervalInMs(
+        Long.parseLong(
+            properties.getProperty(
+                "pipe_memory_allocate_retry_interval_in_ms",
+                
String.valueOf(config.getPipeMemoryAllocateRetryIntervalInMs()))));
   }
 
   public void loadGlobalConfig(TGlobalConfig globalConfig) {
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/pipe/config/PipeConfig.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/pipe/config/PipeConfig.java
index f44dfb60bac..05517648845 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/pipe/config/PipeConfig.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/pipe/config/PipeConfig.java
@@ -157,6 +157,16 @@ public class PipeConfig {
     return COMMON_CONFIG.getPipeMaxAllowedPendingTsFileEpochPerDataRegion();
   }
 
+  /////////////////////////////// Memory ///////////////////////////////
+
+  public int getPipeMemoryAllocateMaxRetries() {
+    return COMMON_CONFIG.getPipeMemoryAllocateMaxRetries();
+  }
+
+  public long getPipeMemoryAllocateRetryIntervalInMs() {
+    return COMMON_CONFIG.getPipeMemoryAllocateRetryIntervalInMs();
+  }
+
   /////////////////////////////// Utils ///////////////////////////////
 
   private static final Logger LOGGER = 
LoggerFactory.getLogger(PipeConfig.class);
@@ -215,6 +225,10 @@ public class PipeConfig {
     LOGGER.info(
         "PipeMaxAllowedPendingTsFileEpochPerDataRegion: {}",
         getPipeMaxAllowedPendingTsFileEpochPerDataRegion());
+
+    LOGGER.info("PipeMemoryAllocateMaxRetries: {}", 
getPipeMemoryAllocateMaxRetries());
+    LOGGER.info(
+        "PipeMemoryAllocateRetryIntervalInMs: {}", 
getPipeMemoryAllocateRetryIntervalInMs());
   }
 
   /////////////////////////////// Singleton ///////////////////////////////

Reply via email to