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

xingtanzjr pushed a commit to branch rel/1.2
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/rel/1.2 by this push:
     new e724c8c8453 [To rel/1.2] add memory estimator on inner space 
compaction (#10691)
e724c8c8453 is described below

commit e724c8c84539f56064a0e6f40b290b4340934c9f
Author: shuwenwei <[email protected]>
AuthorDate: Thu Jul 27 16:12:58 2023 +0800

    [To rel/1.2] add memory estimator on inner space compaction (#10691)
---
 .../execute/task/AbstractCompactionTask.java       |  2 +
 .../execute/task/CrossSpaceCompactionTask.java     |  1 -
 .../execute/task/InnerSpaceCompactionTask.java     | 37 ++++++++-
 .../estimator/AbstractCompactionEstimator.java     |  3 +-
 .../estimator/AbstractInnerSpaceEstimator.java     | 74 ++++++++++++++++-
 .../estimator/CompactionEstimateUtils.java         | 96 ++++++++++++++++++++++
 .../FastCompactionInnerCompactionEstimator.java    | 52 ++++++++++++
 .../compaction/selector/estimator/FileInfo.java    | 48 +++++++++++
 .../ReadChunkInnerCompactionEstimator.java         | 59 +++++++++++++
 .../ReadPointCrossCompactionEstimator.java         | 81 +-----------------
 .../compaction/CompactionSchedulerTest.java        |  1 +
 .../utils/CompactionTaskMemCostEstimatorTest.java  | 94 +++++++++++++++++++++
 .../iotdb/tsfile/read/TsFileSequenceReader.java    | 12 ++-
 13 files changed, 476 insertions(+), 84 deletions(-)

diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/AbstractCompactionTask.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/AbstractCompactionTask.java
index 4502f678b5a..51c9de96889 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/AbstractCompactionTask.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/AbstractCompactionTask.java
@@ -57,6 +57,8 @@ public abstract class AbstractCompactionTask {
   protected boolean crossTask;
   protected boolean innerSeqTask;
 
+  protected long memoryCost = 0L;
+
   protected AbstractCompactionTask(
       String storageGroupName,
       String dataRegionId,
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/CrossSpaceCompactionTask.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/CrossSpaceCompactionTask.java
index a8a74e443da..cfc42efda61 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/CrossSpaceCompactionTask.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/CrossSpaceCompactionTask.java
@@ -61,7 +61,6 @@ public class CrossSpaceCompactionTask extends 
AbstractCompactionTask {
   protected List<TsFileResource> holdWriteLockList = new ArrayList<>();
   protected double selectedSeqFileSize = 0;
   protected double selectedUnseqFileSize = 0;
-  protected long memoryCost = 0L;
 
   @SuppressWarnings("squid:S107")
   public CrossSpaceCompactionTask(
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/InnerSpaceCompactionTask.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/InnerSpaceCompactionTask.java
index 6a843710332..17d70879032 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/InnerSpaceCompactionTask.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/execute/task/InnerSpaceCompactionTask.java
@@ -20,21 +20,29 @@
 package org.apache.iotdb.db.storageengine.dataregion.compaction.execute.task;
 
 import org.apache.iotdb.commons.conf.IoTDBConstant;
+import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.service.metrics.CompactionMetrics;
 import org.apache.iotdb.db.service.metrics.FileMetrics;
 import 
org.apache.iotdb.db.storageengine.dataregion.compaction.execute.exception.CompactionExceptionHandler;
+import 
org.apache.iotdb.db.storageengine.dataregion.compaction.execute.exception.CompactionFileCountExceededException;
+import 
org.apache.iotdb.db.storageengine.dataregion.compaction.execute.exception.CompactionMemoryNotEnoughException;
 import 
org.apache.iotdb.db.storageengine.dataregion.compaction.execute.exception.CompactionValidationFailedException;
 import 
org.apache.iotdb.db.storageengine.dataregion.compaction.execute.performer.ICompactionPerformer;
 import 
org.apache.iotdb.db.storageengine.dataregion.compaction.execute.performer.impl.FastCompactionPerformer;
+import 
org.apache.iotdb.db.storageengine.dataregion.compaction.execute.performer.impl.ReadChunkCompactionPerformer;
 import 
org.apache.iotdb.db.storageengine.dataregion.compaction.execute.task.subtask.FastCompactionTaskSummary;
 import 
org.apache.iotdb.db.storageengine.dataregion.compaction.execute.utils.CompactionUtils;
 import 
org.apache.iotdb.db.storageengine.dataregion.compaction.execute.utils.log.CompactionLogger;
 import 
org.apache.iotdb.db.storageengine.dataregion.compaction.execute.utils.validator.CompactionValidator;
+import 
org.apache.iotdb.db.storageengine.dataregion.compaction.selector.estimator.AbstractInnerSpaceEstimator;
+import 
org.apache.iotdb.db.storageengine.dataregion.compaction.selector.estimator.FastCompactionInnerCompactionEstimator;
+import 
org.apache.iotdb.db.storageengine.dataregion.compaction.selector.estimator.ReadChunkInnerCompactionEstimator;
 import org.apache.iotdb.db.storageengine.dataregion.tsfile.TsFileManager;
 import org.apache.iotdb.db.storageengine.dataregion.tsfile.TsFileResource;
 import org.apache.iotdb.db.storageengine.dataregion.tsfile.TsFileResourceList;
 import 
org.apache.iotdb.db.storageengine.dataregion.tsfile.TsFileResourceStatus;
 import 
org.apache.iotdb.db.storageengine.dataregion.tsfile.generator.TsFileNameGenerator;
+import org.apache.iotdb.db.storageengine.rescon.memory.SystemInfo;
 import org.apache.iotdb.tsfile.common.conf.TSFileConfig;
 import org.apache.iotdb.tsfile.exception.write.TsFileNotCompleteException;
 
@@ -70,6 +78,8 @@ public class InnerSpaceCompactionTask extends 
AbstractCompactionTask {
 
   protected long maxModsFileSize;
 
+  protected AbstractInnerSpaceEstimator innerSpaceEstimator;
+
   public InnerSpaceCompactionTask(
       long timePartition,
       TsFileManager tsFileManager,
@@ -88,6 +98,13 @@ public class InnerSpaceCompactionTask extends 
AbstractCompactionTask {
     this.selectedTsFileResourceList = selectedTsFileResourceList;
     this.sequence = sequence;
     this.performer = performer;
+    if 
(IoTDBDescriptor.getInstance().getConfig().isEnableCompactionMemControl()) {
+      if (this.performer instanceof ReadChunkCompactionPerformer) {
+        innerSpaceEstimator = new ReadChunkInnerCompactionEstimator();
+      } else if (!sequence && this.performer instanceof 
FastCompactionInnerCompactionEstimator) {
+        innerSpaceEstimator = new FastCompactionInnerCompactionEstimator();
+      }
+    }
     isHoldingReadLock = new boolean[selectedTsFileResourceList.size()];
     isHoldingWriteLock = new boolean[selectedTsFileResourceList.size()];
     for (int i = 0; i < selectedTsFileResourceList.size(); ++i) {
@@ -112,6 +129,7 @@ public class InnerSpaceCompactionTask extends 
AbstractCompactionTask {
     if (!tsFileManager.isAllowCompaction()) {
       return true;
     }
+
     long startTime = System.currentTimeMillis();
     // get resource of target file
     String dataDirectory = 
selectedTsFileResourceList.get(0).getTsFile().getParent();
@@ -320,6 +338,8 @@ public class InnerSpaceCompactionTask extends 
AbstractCompactionTask {
             isSequence());
       }
     } finally {
+      SystemInfo.getInstance().resetCompactionMemoryCost(memoryCost);
+      
SystemInfo.getInstance().decreaseCompactionFileNumCost(selectedTsFileResourceList.size());
       releaseAllLocksAndResetStatus();
     }
     return isSuccess;
@@ -456,9 +476,24 @@ public class InnerSpaceCompactionTask extends 
AbstractCompactionTask {
           return false;
         }
       }
+      if (innerSpaceEstimator != null) {
+        memoryCost = 
innerSpaceEstimator.estimateInnerCompactionMemory(selectedTsFileResourceList);
+      }
+      SystemInfo.getInstance().addCompactionMemoryCost(memoryCost, 60);
+      
SystemInfo.getInstance().addCompactionFileNum(selectedTsFileResourceList.size(),
 60);
     } catch (Exception e) {
+      if (e instanceof InterruptedException) {
+        LOGGER.warn("Interrupted when allocating memory for compaction", e);
+        Thread.currentThread().interrupt();
+      } else if (e instanceof CompactionMemoryNotEnoughException) {
+        LOGGER.info("No enough memory for current compaction task {}", this, 
e);
+      } else if (e instanceof CompactionFileCountExceededException) {
+        LOGGER.info("No enough file num for current compaction task {}", this, 
e);
+        SystemInfo.getInstance().resetCompactionMemoryCost(memoryCost);
+      }
+      resetCompactionCandidateStatusForAllSourceFiles();
       releaseAllLocksAndResetStatus();
-      throw e;
+      return false;
     }
     return true;
   }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/selector/estimator/AbstractCompactionEstimator.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/selector/estimator/AbstractCompactionEstimator.java
index 3d53867232b..c4450637344 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/selector/estimator/AbstractCompactionEstimator.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/selector/estimator/AbstractCompactionEstimator.java
@@ -52,7 +52,8 @@ public abstract class AbstractCompactionEstimator {
       List<TsFileResource> seqResources, TsFileResource unseqResource) throws 
IOException;
 
   /** Estimate the memory cost of compacting the source files in inner space 
compaction task. */
-  public abstract long estimateInnerCompactionMemory(List<TsFileResource> 
resources);
+  public abstract long estimateInnerCompactionMemory(List<TsFileResource> 
resources)
+      throws IOException;
 
   /**
    * Construct a new or get an existing TsFileSequenceReader of a TsFile.
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/selector/estimator/AbstractInnerSpaceEstimator.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/selector/estimator/AbstractInnerSpaceEstimator.java
index cc34bd28cc4..a5309aaff30 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/selector/estimator/AbstractInnerSpaceEstimator.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/selector/estimator/AbstractInnerSpaceEstimator.java
@@ -19,9 +19,14 @@
 
 package 
org.apache.iotdb.db.storageengine.dataregion.compaction.selector.estimator;
 
+import org.apache.iotdb.db.conf.IoTDBConfig;
+import org.apache.iotdb.db.conf.IoTDBDescriptor;
+import 
org.apache.iotdb.db.storageengine.dataregion.modification.ModificationFile;
 import org.apache.iotdb.db.storageengine.dataregion.tsfile.TsFileResource;
+import org.apache.iotdb.tsfile.read.TsFileSequenceReader;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -29,11 +34,78 @@ import java.util.List;
  * its corresponding implementation.
  */
 public abstract class AbstractInnerSpaceEstimator extends 
AbstractCompactionEstimator {
-  public abstract long estimateInnerCompactionMemory(List<TsFileResource> 
resources);
+  protected IoTDBConfig config = IoTDBDescriptor.getInstance().getConfig();
+
+  public long estimateInnerCompactionMemory(List<TsFileResource> resources) 
throws IOException {
+    InnerCompactionTaskInfo taskInfo = 
calculatingCompactionTaskInfo(resources);
+    long cost = calculatingMetadataMemoryCost(taskInfo);
+    cost += calculatingDataMemoryCost(taskInfo);
+    return cost;
+  }
+
+  public abstract long calculatingMetadataMemoryCost(InnerCompactionTaskInfo 
taskInfo);
+
+  public abstract long calculatingDataMemoryCost(InnerCompactionTaskInfo 
taskInfo);
 
   public long estimateCrossCompactionMemory(
       List<TsFileResource> seqResources, TsFileResource unseqResource) throws 
IOException {
     throw new RuntimeException(
         "This kind of estimator cannot be used to estimate cross space 
compaction task");
   }
+
+  protected InnerCompactionTaskInfo 
calculatingCompactionTaskInfo(List<TsFileResource> resources)
+      throws IOException {
+    List<FileInfo> fileInfoList = new ArrayList<>();
+    for (TsFileResource resource : resources) {
+      TsFileSequenceReader reader = getFileReader(resource);
+      FileInfo fileInfo = 
CompactionEstimateUtils.getSeriesAndDeviceChunkNum(reader);
+      fileInfoList.add(fileInfo);
+    }
+    return new InnerCompactionTaskInfo(resources, fileInfoList);
+  }
+
+  protected static class InnerCompactionTaskInfo {
+    private final List<FileInfo> fileInfoList;
+    private int maxConcurrentSeriesNum = 1;
+    private long maxChunkMetadataSize = 0;
+    private int maxChunkMetadataNumInDevice = 0;
+    private long modificationFileSize = 0;
+
+    protected InnerCompactionTaskInfo(List<TsFileResource> resources, 
List<FileInfo> fileInfoList) {
+      this.fileInfoList = fileInfoList;
+      for (TsFileResource resource : resources) {
+        ModificationFile modificationFile = resource.getModFile();
+        if (modificationFile.exists()) {
+          modificationFileSize += modificationFile.getSize();
+        }
+      }
+      for (FileInfo fileInfo : fileInfoList) {
+        maxConcurrentSeriesNum =
+            Math.max(maxConcurrentSeriesNum, 
fileInfo.maxAlignedSeriesNumInDevice);
+        maxChunkMetadataNumInDevice =
+            Math.max(maxChunkMetadataNumInDevice, fileInfo.maxDeviceChunkNum);
+        maxChunkMetadataSize = Math.max(maxChunkMetadataSize, 
fileInfo.averageChunkMetadataSize);
+      }
+    }
+
+    public int getMaxChunkMetadataNumInDevice() {
+      return maxChunkMetadataNumInDevice;
+    }
+
+    public long getMaxChunkMetadataSize() {
+      return maxChunkMetadataSize;
+    }
+
+    public List<FileInfo> getFileInfoList() {
+      return fileInfoList;
+    }
+
+    public int getMaxConcurrentSeriesNum() {
+      return maxConcurrentSeriesNum;
+    }
+
+    public long getModificationFileSize() {
+      return modificationFileSize;
+    }
+  }
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/selector/estimator/CompactionEstimateUtils.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/selector/estimator/CompactionEstimateUtils.java
new file mode 100644
index 00000000000..fe6f24fcfb4
--- /dev/null
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/selector/estimator/CompactionEstimateUtils.java
@@ -0,0 +1,96 @@
+/*
+ * 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.storageengine.dataregion.compaction.selector.estimator;
+
+import org.apache.iotdb.db.storageengine.dataregion.tsfile.TsFileResource;
+import org.apache.iotdb.tsfile.file.metadata.TimeseriesMetadata;
+import org.apache.iotdb.tsfile.read.TsFileSequenceReader;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+public class CompactionEstimateUtils {
+
+  /**
+   * Get the details of the tsfile, the returned array contains the following 
elements in sequence:
+   *
+   * <p>total chunk num in this tsfile
+   *
+   * <p>max chunk num of one timeseries in this tsfile
+   *
+   * <p>max aligned series num in one device. If there is no aligned series in 
this file, then it
+   * turns to be -1.
+   *
+   * <p>max chunk num of one device in this tsfile
+   *
+   * @throws IOException if io errors occurred
+   */
+  public static FileInfo getSeriesAndDeviceChunkNum(TsFileSequenceReader 
reader)
+      throws IOException {
+    int totalChunkNum = 0;
+    int maxChunkNum = 0;
+    int maxAlignedSeriesNumInDevice = -1;
+    int maxDeviceChunkNum = 0;
+    Map<String, List<TimeseriesMetadata>> deviceMetadata = 
reader.getAllTimeseriesMetadata(true);
+    for (Map.Entry<String, List<TimeseriesMetadata>> entry : 
deviceMetadata.entrySet()) {
+      int deviceChunkNum = 0;
+      List<TimeseriesMetadata> deviceTimeseriesMetadata = entry.getValue();
+      if (deviceTimeseriesMetadata.get(0).getMeasurementId().equals("")) {
+        // aligned device
+        maxAlignedSeriesNumInDevice =
+            Math.max(maxAlignedSeriesNumInDevice, 
deviceTimeseriesMetadata.size());
+      }
+      for (TimeseriesMetadata timeseriesMetadata : deviceTimeseriesMetadata) {
+        deviceChunkNum += timeseriesMetadata.getChunkMetadataList().size();
+        totalChunkNum += timeseriesMetadata.getChunkMetadataList().size();
+        maxChunkNum = Math.max(maxChunkNum, 
timeseriesMetadata.getChunkMetadataList().size());
+      }
+      maxDeviceChunkNum = Math.max(maxDeviceChunkNum, deviceChunkNum);
+    }
+    long averageChunkMetadataSize =
+        totalChunkNum == 0 ? 0 : reader.getAllMetadataSize() / totalChunkNum;
+    return new FileInfo(
+        totalChunkNum,
+        maxChunkNum,
+        maxAlignedSeriesNumInDevice,
+        maxDeviceChunkNum,
+        averageChunkMetadataSize);
+  }
+
+  public static boolean addReadLock(List<TsFileResource> resources) {
+    for (int i = 0; i < resources.size(); i++) {
+      TsFileResource resource = resources.get(i);
+      resource.readLock();
+      if (resource.isDeleted()) {
+        // release read lock
+        for (int j = 0; j <= i; j++) {
+          resources.get(j).readUnlock();
+        }
+        return false;
+      }
+    }
+    return true;
+  }
+
+  public static void releaseReadLock(List<TsFileResource> resources) {
+    resources.forEach(TsFileResource::readUnlock);
+  }
+}
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/selector/estimator/FastCompactionInnerCompactionEstimator.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/selector/estimator/FastCompactionInnerCompactionEstimator.java
new file mode 100644
index 00000000000..9de3f58af9b
--- /dev/null
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/selector/estimator/FastCompactionInnerCompactionEstimator.java
@@ -0,0 +1,52 @@
+/*
+ * 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.storageengine.dataregion.compaction.selector.estimator;
+
+public class FastCompactionInnerCompactionEstimator extends 
AbstractInnerSpaceEstimator {
+
+  /**
+   * The metadata algorithm is: maxChunkMetaDataSize * maxChunkNumber * 
fileSize * maxSeriesNumber
+   *
+   * @return estimate metadata memory cost
+   */
+  @Override
+  public long calculatingMetadataMemoryCost(InnerCompactionTaskInfo taskInfo) {
+    return taskInfo.getFileInfoList().size()
+        * taskInfo.getMaxChunkMetadataNumInDevice()
+        * taskInfo.getMaxChunkMetadataSize()
+        * Math.max(config.getSubCompactionTaskNum(), 
taskInfo.getMaxConcurrentSeriesNum());
+  }
+
+  /**
+   * The data algorithm is: (targetChunkSize * fileSize * compressionRatio * 
maxSeriesNumber) +
+   * modsFileSize
+   *
+   * @return estimate data memory cost
+   */
+  @Override
+  public long calculatingDataMemoryCost(InnerCompactionTaskInfo taskInfo) {
+    long cost =
+        config.getTargetChunkSize()
+            * taskInfo.getFileInfoList().size()
+            * Math.max(config.getSubCompactionTaskNum(), 
taskInfo.getMaxConcurrentSeriesNum());
+    cost += taskInfo.getModificationFileSize();
+    return cost;
+  }
+}
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/selector/estimator/FileInfo.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/selector/estimator/FileInfo.java
new file mode 100644
index 00000000000..7ff1ae9be3d
--- /dev/null
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/selector/estimator/FileInfo.java
@@ -0,0 +1,48 @@
+/*
+ * 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.storageengine.dataregion.compaction.selector.estimator;
+
+public class FileInfo {
+  // total chunk num in this tsfile
+  int totalChunkNum = 0;
+  // max chunk num of one timeseries in this tsfile
+  int maxSeriesChunkNum = 0;
+  // max aligned series num in one device. If there is no aligned series in 
this file, then it
+  // turns to be -1.
+  int maxAlignedSeriesNumInDevice = -1;
+  // max chunk num of one device in this tsfile
+  @SuppressWarnings("squid:S1068")
+  int maxDeviceChunkNum = 0;
+
+  long averageChunkMetadataSize = 0;
+
+  public FileInfo(
+      int totalChunkNum,
+      int maxSeriesChunkNum,
+      int maxAlignedSeriesNumInDevice,
+      int maxDeviceChunkNum,
+      long averageChunkMetadataSize) {
+    this.totalChunkNum = totalChunkNum;
+    this.maxSeriesChunkNum = maxSeriesChunkNum;
+    this.maxAlignedSeriesNumInDevice = maxAlignedSeriesNumInDevice;
+    this.maxDeviceChunkNum = maxDeviceChunkNum;
+    this.averageChunkMetadataSize = averageChunkMetadataSize;
+  }
+}
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/selector/estimator/ReadChunkInnerCompactionEstimator.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/selector/estimator/ReadChunkInnerCompactionEstimator.java
new file mode 100644
index 00000000000..02924768952
--- /dev/null
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/selector/estimator/ReadChunkInnerCompactionEstimator.java
@@ -0,0 +1,59 @@
+/*
+ * 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.storageengine.dataregion.compaction.selector.estimator;
+
+import org.apache.iotdb.db.conf.IoTDBDescriptor;
+import org.apache.iotdb.db.storageengine.rescon.memory.SystemInfo;
+
+public class ReadChunkInnerCompactionEstimator extends 
AbstractInnerSpaceEstimator {
+
+  @Override
+  public long calculatingMetadataMemoryCost(InnerCompactionTaskInfo taskInfo) {
+    long cost = 0;
+    // add ChunkMetadata size of MultiTsFileDeviceIterator
+    cost +=
+        taskInfo.getFileInfoList().size()
+            * taskInfo.getMaxChunkMetadataNumInDevice()
+            * taskInfo.getMaxChunkMetadataSize();
+
+    // add ChunkMetadata size of targetFileWriter
+    long sizeForFileWriter =
+        (long)
+            ((double) SystemInfo.getInstance().getMemorySizeForCompaction()
+                / 
IoTDBDescriptor.getInstance().getConfig().getCompactionThreadCount()
+                * 
IoTDBDescriptor.getInstance().getConfig().getChunkMetadataSizeProportion());
+    cost += sizeForFileWriter;
+
+    return cost;
+  }
+
+  @Override
+  public long calculatingDataMemoryCost(InnerCompactionTaskInfo taskInfo) {
+    // add max target chunk size and max source chunk size
+    long cost =
+        2
+            * taskInfo.getMaxConcurrentSeriesNum()
+            * IoTDBDescriptor.getInstance().getConfig().getTargetChunkSize();
+
+    // add modification file size
+    cost += taskInfo.getModificationFileSize();
+    return cost;
+  }
+}
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/selector/estimator/ReadPointCrossCompactionEstimator.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/selector/estimator/ReadPointCrossCompactionEstimator.java
index 318420a831f..d8908cfd0e6 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/selector/estimator/ReadPointCrossCompactionEstimator.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/compaction/selector/estimator/ReadPointCrossCompactionEstimator.java
@@ -22,7 +22,6 @@ package 
org.apache.iotdb.db.storageengine.dataregion.compaction.selector.estimat
 import org.apache.iotdb.commons.conf.IoTDBConstant;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.storageengine.dataregion.tsfile.TsFileResource;
-import org.apache.iotdb.tsfile.file.metadata.TimeseriesMetadata;
 import org.apache.iotdb.tsfile.read.TsFileSequenceReader;
 
 import org.slf4j.Logger;
@@ -31,7 +30,6 @@ import org.slf4j.LoggerFactory;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
 
 public class ReadPointCrossCompactionEstimator extends 
AbstractCrossSpaceEstimator {
   private static final Logger logger =
@@ -77,18 +75,7 @@ public class ReadPointCrossCompactionEstimator extends 
AbstractCrossSpaceEstimat
   private boolean addReadLock(List<TsFileResource> seqResources, 
TsFileResource unseqResource) {
     List<TsFileResource> allResources = new ArrayList<>(seqResources);
     allResources.add(unseqResource);
-    for (int i = 0; i < allResources.size(); i++) {
-      TsFileResource resource = allResources.get(i);
-      resource.readLock();
-      if (resource.isDeleted()) {
-        // release read lock
-        for (int j = 0; j <= i; j++) {
-          allResources.get(j).readUnlock();
-        }
-        return false;
-      }
-    }
-    return true;
+    return CompactionEstimateUtils.addReadLock(allResources);
   }
 
   private void releaseReadLock(List<TsFileResource> seqResources, 
TsFileResource unseqResource) {
@@ -104,7 +91,7 @@ public class ReadPointCrossCompactionEstimator extends 
AbstractCrossSpaceEstimat
    */
   private long calculateReadingUnseqFile(TsFileResource unseqResource) throws 
IOException {
     TsFileSequenceReader reader = getFileReader(unseqResource);
-    FileInfo fileInfo = getSeriesAndDeviceChunkNum(reader);
+    FileInfo fileInfo = 
CompactionEstimateUtils.getSeriesAndDeviceChunkNum(reader);
     // it is max aligned series num of one device when tsfile contains aligned 
series,
     // else is sub compaction task num.
     int concurrentSeriesNum =
@@ -141,7 +128,7 @@ public class ReadPointCrossCompactionEstimator extends 
AbstractCrossSpaceEstimat
     long cost = 0;
     for (TsFileResource seqResource : seqResources) {
       TsFileSequenceReader reader = getFileReader(seqResource);
-      FileInfo fileInfo = getSeriesAndDeviceChunkNum(reader);
+      FileInfo fileInfo = 
CompactionEstimateUtils.getSeriesAndDeviceChunkNum(reader);
       // it is max aligned series num of one device when tsfile contains 
aligned series,
       // else is sub compaction task num.
       int concurrentSeriesNum =
@@ -207,66 +194,4 @@ public class ReadPointCrossCompactionEstimator extends 
AbstractCrossSpaceEstimat
 
     return cost;
   }
-
-  /**
-   * Get the details of the tsfile, the returned array contains the following 
elements in sequence:
-   *
-   * <p>total chunk num in this tsfile
-   *
-   * <p>max chunk num of one timeseries in this tsfile
-   *
-   * <p>max aligned series num in one device. If there is no aligned series in 
this file, then it
-   * turns to be -1.
-   *
-   * <p>max chunk num of one device in this tsfile
-   *
-   * @throws IOException if io errors occurred
-   */
-  private FileInfo getSeriesAndDeviceChunkNum(TsFileSequenceReader reader) 
throws IOException {
-    int totalChunkNum = 0;
-    int maxChunkNum = 0;
-    int maxAlignedSeriesNumInDevice = -1;
-    int maxDeviceChunkNum = 0;
-    Map<String, List<TimeseriesMetadata>> deviceMetadata = 
reader.getAllTimeseriesMetadata(true);
-    for (Map.Entry<String, List<TimeseriesMetadata>> entry : 
deviceMetadata.entrySet()) {
-      int deviceChunkNum = 0;
-      List<TimeseriesMetadata> deviceTimeseriesMetadata = entry.getValue();
-      if (deviceTimeseriesMetadata.get(0).getMeasurementId().equals("")) {
-        // aligned device
-        maxAlignedSeriesNumInDevice =
-            Math.max(maxAlignedSeriesNumInDevice, 
deviceTimeseriesMetadata.size());
-      }
-      for (TimeseriesMetadata timeseriesMetadata : deviceTimeseriesMetadata) {
-        deviceChunkNum += timeseriesMetadata.getChunkMetadataList().size();
-        totalChunkNum += timeseriesMetadata.getChunkMetadataList().size();
-        maxChunkNum = Math.max(maxChunkNum, 
timeseriesMetadata.getChunkMetadataList().size());
-      }
-      maxDeviceChunkNum = Math.max(maxDeviceChunkNum, deviceChunkNum);
-    }
-    return new FileInfo(totalChunkNum, maxChunkNum, 
maxAlignedSeriesNumInDevice, maxDeviceChunkNum);
-  }
-
-  private class FileInfo {
-    // total chunk num in this tsfile
-    private int totalChunkNum = 0;
-    // max chunk num of one timeseries in this tsfile
-    private int maxSeriesChunkNum = 0;
-    // max aligned series num in one device. If there is no aligned series in 
this file, then it
-    // turns to be -1.
-    private int maxAlignedSeriesNumInDevice = -1;
-    // max chunk num of one device in this tsfile
-    @SuppressWarnings("squid:S1068")
-    private int maxDeviceChunkNum = 0;
-
-    public FileInfo(
-        int totalChunkNum,
-        int maxSeriesChunkNum,
-        int maxAlignedSeriesNumInDevice,
-        int maxDeviceChunkNum) {
-      this.totalChunkNum = totalChunkNum;
-      this.maxSeriesChunkNum = maxSeriesChunkNum;
-      this.maxAlignedSeriesNumInDevice = maxAlignedSeriesNumInDevice;
-      this.maxDeviceChunkNum = maxDeviceChunkNum;
-    }
-  }
 }
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/CompactionSchedulerTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/CompactionSchedulerTest.java
index 198e865dd07..d417eab7f7f 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/CompactionSchedulerTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/CompactionSchedulerTest.java
@@ -101,6 +101,7 @@ public class CompactionSchedulerTest {
         .getConfig()
         
.setInnerUnseqCompactionPerformer(InnerUnseqCompactionPerformer.READ_POINT);
     
IoTDBDescriptor.getInstance().getConfig().setMinCrossCompactionUnseqFileLevel(0);
+    
IoTDBDescriptor.getInstance().getConfig().setEnableCompactionMemControl(false);
     CompactionTaskManager.getInstance().start();
     while (CompactionTaskManager.getInstance().getExecutingTaskCount() > 0) {
       try {
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/utils/CompactionTaskMemCostEstimatorTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/utils/CompactionTaskMemCostEstimatorTest.java
new file mode 100644
index 00000000000..fc0e5d3d4c4
--- /dev/null
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/utils/CompactionTaskMemCostEstimatorTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.storageengine.dataregion.compaction.utils;
+
+import org.apache.iotdb.commons.exception.MetadataException;
+import org.apache.iotdb.db.exception.StorageEngineException;
+import 
org.apache.iotdb.db.storageengine.dataregion.compaction.AbstractCompactionTest;
+import 
org.apache.iotdb.db.storageengine.dataregion.compaction.selector.estimator.FastCompactionInnerCompactionEstimator;
+import 
org.apache.iotdb.db.storageengine.dataregion.compaction.selector.estimator.ReadChunkInnerCompactionEstimator;
+import org.apache.iotdb.db.storageengine.dataregion.tsfile.TsFileResource;
+import org.apache.iotdb.tsfile.exception.write.WriteProcessException;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.List;
+
+public class CompactionTaskMemCostEstimatorTest extends AbstractCompactionTest 
{
+
+  @Before
+  public void setUp()
+      throws IOException, WriteProcessException, MetadataException, 
InterruptedException {
+    super.setUp();
+  }
+
+  @After
+  public void tearDown() throws IOException, StorageEngineException {
+    super.tearDown();
+  }
+
+  @Test
+  public void testEstimateReadChunkInnerSpaceCompactionTaskMemCost()
+      throws IOException, MetadataException, WriteProcessException {
+    createFiles(3, 10, 5, 100000, 0, 0, 50, 50, true, true);
+    tsFileManager.addAll(seqResources, true);
+    List<TsFileResource> tsFileList = tsFileManager.getTsFileList(true);
+    System.out.println(tsFileList.get(0).getTsFile().getAbsolutePath());
+    long cost = new 
ReadChunkInnerCompactionEstimator().estimateInnerCompactionMemory(tsFileList);
+    Assert.assertTrue(cost > 0);
+  }
+
+  @Test
+  public void testEstimateReadChunkInnerSpaceCompactionTaskMemCost2()
+      throws IOException, MetadataException, WriteProcessException {
+    createFiles(3, 10, 5, 100, 0, 0, 50, 50, false, true);
+    tsFileManager.addAll(seqResources, true);
+    List<TsFileResource> tsFileList = tsFileManager.getTsFileList(true);
+    long cost = new 
ReadChunkInnerCompactionEstimator().estimateInnerCompactionMemory(tsFileList);
+    Assert.assertTrue(cost > 0);
+  }
+
+  @Test
+  public void testEstimateFastCompactionInnerSpaceCompactionTaskMemCost()
+      throws IOException, MetadataException, WriteProcessException {
+    createFiles(3, 10, 5, 100000, 0, 0, 50, 50, true, true);
+    tsFileManager.addAll(seqResources, true);
+    List<TsFileResource> tsFileList = tsFileManager.getTsFileList(true);
+    System.out.println(tsFileList.get(0).getTsFile().getAbsolutePath());
+    long cost =
+        new 
FastCompactionInnerCompactionEstimator().estimateInnerCompactionMemory(tsFileList);
+    Assert.assertTrue(cost > 0);
+  }
+
+  @Test
+  public void testEstimateFastCompactionInnerSpaceCompactionTaskMemCost2()
+      throws IOException, MetadataException, WriteProcessException {
+    createFiles(3, 10, 5, 100, 0, 0, 50, 50, false, true);
+    tsFileManager.addAll(seqResources, true);
+    List<TsFileResource> tsFileList = tsFileManager.getTsFileList(true);
+    long cost =
+        new 
FastCompactionInnerCompactionEstimator().estimateInnerCompactionMemory(tsFileList);
+    Assert.assertTrue(cost > 0);
+  }
+}
diff --git 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/TsFileSequenceReader.java
 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/TsFileSequenceReader.java
index 56602d07b09..b1742330c2c 100644
--- 
a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/TsFileSequenceReader.java
+++ 
b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/TsFileSequenceReader.java
@@ -228,12 +228,20 @@ public class TsFileSequenceReader implements 
AutoCloseable {
     return fileMetadataSize;
   }
 
+  /** Return the tsfile meta data size of this tsfile. */
+  public long getFileMetadataSize() throws IOException {
+    return tsFileInput.size() - getFileMetadataPos();
+  }
+
   /**
    * Return the whole meta data size of this tsfile, including ChunkMetadata, 
TimeseriesMetadata and
    * etc.
    */
-  public long getFileMetadataSize() throws IOException {
-    return tsFileInput.size() - getFileMetadataPos();
+  public long getAllMetadataSize() throws IOException {
+    if (tsFileMetaData == null) {
+      readFileMetadata();
+    }
+    return tsFileInput.size() - tsFileMetaData.getMetaOffset();
   }
 
   /** this function does not modify the position of the file reader. */


Reply via email to