JackieTien97 commented on code in PR #18409:
URL: https://github.com/apache/iotdb/pull/18409#discussion_r3749226841


##########
iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/datastructure/AlignedTVListTest.java:
##########
@@ -586,4 +589,166 @@ public void testCalculateChunkSize() {
     Assert.assertEquals(tvList.memoryBinaryChunkSize[0], 0);
     Assert.assertEquals(tvList.memoryBinaryChunkSize[1], 0);
   }
+
+  @Test
+  public void testMovesUnclonedColumns() {
+    List<TSDataType> dataTypes = new ArrayList<>();
+    for (int i = 0; i < 3; i++) {
+      dataTypes.add(TSDataType.INT64);
+    }
+    AlignedTVList tvList = AlignedTVList.newAlignedList(dataTypes);
+    tvList.putAlignedValue(0, new Object[] {1L, 2L, null});
+
+    Set<Integer> columnsToClone = Collections.singleton(1);
+    long retainedRamSize = 
tvList.calculateRamSize(columnsToClone).getRamSize();
+    AlignedTVList.PartialClonePlan partialClonePlan = 
tvList.preparePartialClone(columnsToClone);
+    AlignedTVList clonedTvList = partialClonePlan.getCloneList();
+
+    Assert.assertNotNull(tvList.getValues().get(0));
+    Assert.assertNotNull(tvList.getValues().get(2));
+    Assert.assertEquals(1L, tvList.getLongByValueIndex(0, 0));
+    Assert.assertTrue(tvList.isNullValue(0, 2));
+    Assert.assertEquals(2L, clonedTvList.getLongByValueIndex(0, 1));
+
+    partialClonePlan.commit();
+
+    Assert.assertNull(tvList.getValues().get(0));
+    Assert.assertNull(tvList.getValues().get(2));
+    Assert.assertTrue(tvList.isNullValue(0, 0));
+    Assert.assertTrue(tvList.isNullValue(0, 2));
+    Assert.assertEquals(1L, clonedTvList.getLongByValueIndex(0, 0));
+    Assert.assertEquals(2L, clonedTvList.getLongByValueIndex(0, 1));
+    Assert.assertTrue(clonedTvList.isNullValue(0, 2));
+    Assert.assertEquals(retainedRamSize, 
tvList.calculateRamSize().getRamSize());
+  }
+
+  @Test
+  public void testPartialRamSizeScalesWithRetainedColumns() {
+    int columnCount = 256;
+    List<TSDataType> dataTypes = new ArrayList<>(columnCount);
+    Object[] values = new Object[columnCount];
+    for (int i = 0; i < columnCount; i++) {
+      dataTypes.add(TSDataType.INT64);
+      values[i] = (long) i;
+    }
+
+    AlignedTVList tvList = AlignedTVList.newAlignedList(dataTypes);
+    tvList.putAlignedValue(1, values);
+    Set<Integer> retainedColumns = Collections.singleton(0);
+    long retainedRamSize = 
tvList.calculateRamSize(retainedColumns).getRamSize();
+    long fullRamSize = tvList.calculateRamSize().getRamSize();
+
+    // Only the retained column's materialized arrays are charged, so keeping 
1 of 256 columns
+    // must cost far less than the full list.
+    Assert.assertTrue(retainedRamSize < fullRamSize / 64);

Review Comment:
   **[P1] Restore the focused unit suite after changing the RAM model**
   
   At the latest head, `mvn test -pl iotdb-core/datanode -am 
-Dtest=AlignedTVListTest,FragmentInstanceExecutionTest 
-Dsurefire.failIfNoSpecifiedTests=false -DfailIfNoTests=false` runs the 
end-to-end fragment tests successfully but fails 5 of the 23 
`AlignedTVListTest` cases. This assertion can no longer hold because the 
retained source intentionally keeps an N-wide fixed container baseline; four 
existing delta/absolute-size assertions likewise omit the newly added one-time 
container costs. Please update the affected invariants and expectations for the 
new model (including a fixed N-wide baseline plus the variable retained 
payload) and make the focused suite pass rather than weakening this ratio in 
isolation.



##########
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/AlignedTVList.java:
##########
@@ -212,39 +269,190 @@ public synchronized AlignedTVList cloneForFlushSort() {
   public synchronized AlignedTVList clone() {
     AlignedTVList cloneList = AlignedTVList.newAlignedList(new 
ArrayList<>(dataTypes));
     cloneAs(cloneList);
-    cloneList.timeDeletedCnt = this.timeDeletedCnt;
-    System.arraycopy(
-        memoryBinaryChunkSize, 0, cloneList.memoryBinaryChunkSize, 0, 
dataTypes.size());
+    cloneColumnDataTo(cloneList, null);
+    cloneList.materializedValueArrayCounts =
+        Arrays.copyOf(materializedValueArrayCounts, 
materializedValueArrayCounts.length);
+    cloneList.materializedValueArrayMemCost = materializedValueArrayMemCost;
+    return cloneList;
+  }
+
+  /**
+   * Prepare a partial clone without changing this TVList. The returned plan 
must be committed only
+   * after the query-memory reservation succeeds.
+   */
+  public synchronized PartialClonePlan preparePartialClone(Set<Integer> 
columnsToClone) {
+    Set<Integer> retainedColumns =
+        new HashSet<>(
+            Objects.requireNonNull(
+                columnsToClone,
+                
DataNodeMiscMessages.EXCEPTION_COLUMNSTOCLONE_CANNOT_BE_NULL_458FDF37));
+    AlignedTVList cloneList = AlignedTVList.newAlignedList(new 
ArrayList<>(dataTypes), false);
+    // Pre-create the inner value lists for the retained columns; the other 
slots stay null until
+    // the ownership transfer moves the source columns into place.
     for (int i = 0; i < values.size(); i++) {
-      // Clone value
+      if (retainedColumns.contains(i)) {
+        cloneList.values.set(i, new ArrayList<>(values.get(i).size()));
+      }
+    }
+    cloneAs(cloneList);
+    cloneColumnDataTo(cloneList, retainedColumns);
+    return prepareMovePlan(cloneList, retainedColumns);
+  }
+
+  @SuppressWarnings("unchecked")
+  private PartialClonePlan prepareMovePlan(AlignedTVList cloneList, 
Set<Integer> retainedColumns) {
+    Objects.requireNonNull(
+        cloneList, 
DataNodeMiscMessages.EXCEPTION_CLONELIST_CANNOT_BE_NULL_47AEEA8F);
+    int columnCount = values.size();
+    if (cloneList.values.size() != columnCount
+        || cloneList.memoryBinaryChunkSize.length != 
memoryBinaryChunkSize.length) {
+      throw new IllegalStateException(
+          DataNodeMiscMessages
+              
.EXCEPTION_TARGET_ALIGNEDTVLIST_HAS_INCOMPATIBLE_COLUMN_CONTAINERS_31FAC613);
+    }
+
+    List<Object>[] valueColumnsToMove = (List<Object>[]) new 
List<?>[columnCount];
+    List<BitMap>[] bitmapColumnsToMove = (List<BitMap>[]) new 
List<?>[columnCount];

Review Comment:
   **[P1] Account for the remaining O(N) move-plan arrays**
   
   The new partial constructor removes the per-column empty inner lists, but 
preparation still allocates these two `columnCount` arrays after the caller has 
reserved only `listRamInfo`, which represents the final retained source. The 
prepared clone already consumes roughly that reservation, while these arrays 
coexist with it and are absent from both final lists' accounting. For a wide 
aligned device this leaves an unprotected `2 * N * NUM_BYTES_OBJECT_REF` peak, 
so the admission-control issue is only partially fixed. Please either eliminate 
these arrays (for example, validate first and move by the retained-column set 
during an allocation-free commit) or reserve and release their exact temporary 
cost, with a wide peak-accounting test.



##########
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/AlignedTVList.java:
##########
@@ -188,7 +246,6 @@ public TVList getTvListByColumnIndex(
             (long) materializedArrayCount * 
valueListArrayMemCost(dataTypeList.get(i));

Review Comment:
   **[P2] Do not count projected value-slot references twice**
   
   `calculateContainerRamCost` now charges every reference in each retained 
`columnValues` backing array. The normal materialization path was accordingly 
changed to cache only `primitiveArrayMemCost`, but this projected-list path 
still caches `valueListArrayMemCost`, which includes the slot reference. 
Consequently every materialized projected block is overcounted by 
`NUM_BYTES_OBJECT_REF`, making `calculateRamSize()` depend on how the list was 
constructed. Please use `primitiveArrayMemCost` here as well and add a 
projected-list RAM assertion under the new container model.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to