|
28 | 28 | import org.apache.iotdb.commons.path.PartialPath; |
29 | 29 | import org.apache.iotdb.commons.queryengine.plan.planner.plan.node.PlanNodeId; |
30 | 30 | import org.apache.iotdb.commons.schema.table.column.TsTableColumnCategory; |
| 31 | +import org.apache.iotdb.commons.utils.TestOnly; |
31 | 32 | import org.apache.iotdb.db.i18n.DataNodePipeMessages; |
32 | 33 | import org.apache.iotdb.db.queryengine.plan.planner.plan.node.write.InsertMultiTabletsNode; |
33 | 34 | import org.apache.iotdb.db.queryengine.plan.planner.plan.node.write.InsertNode; |
@@ -155,6 +156,12 @@ public class InsertNodeMemoryEstimator { |
155 | 156 | // from the actual result because the properties of the parent class are not added. |
156 | 157 | private static final double INSERT_ROW_NODE_EXPANSION_FACTOR = 1.3; |
157 | 158 |
|
| 159 | + // Composite insert nodes are estimated on write threads. Reuse the identity set between events, |
| 160 | + // but discard unusually large sets to avoid retaining a large table on every write thread. |
| 161 | + private static final int MAX_RETAINED_DEDUPLICATED_OBJECTS = 1024; |
| 162 | + private static final ThreadLocal<Set<Object>> REUSABLE_DEDUPLICATED_OBJECTS = |
| 163 | + ThreadLocal.withInitial(InsertNodeMemoryEstimator::newDeduplicatedObjectSet); |
| 164 | + |
158 | 165 | public static long sizeOf(final InsertNode insertNode) { |
159 | 166 | try { |
160 | 167 | final String className = insertNode.getClass().getSimpleName(); |
@@ -248,46 +255,62 @@ private static long sizeOfInsertRowNode( |
248 | 255 |
|
249 | 256 | private static long sizeOfInsertRowsNode(final InsertRowsNode node) { |
250 | 257 | final Set<Object> deduplicatedObjects = |
251 | | - newDeduplicatedObjectSetIfNeeded(node.getInsertRowNodeList()); |
252 | | - long size = INSERT_ROWS_NODE_SIZE; |
253 | | - size += calculateFullInsertNodeSize(node, deduplicatedObjects); |
254 | | - size += sizeOfInsertRowNodeList(node.getInsertRowNodeList(), deduplicatedObjects); |
255 | | - size += sizeOfIntegerList(node.getInsertRowNodeIndexList()); |
256 | | - size += sizeOfResults(node.getResults()); |
257 | | - return size; |
| 258 | + acquireDeduplicatedObjectSetIfNeeded(node.getInsertRowNodeList()); |
| 259 | + try { |
| 260 | + long size = INSERT_ROWS_NODE_SIZE; |
| 261 | + size += calculateFullInsertNodeSize(node, deduplicatedObjects); |
| 262 | + size += sizeOfInsertRowNodeList(node.getInsertRowNodeList(), deduplicatedObjects); |
| 263 | + size += sizeOfIntegerList(node.getInsertRowNodeIndexList()); |
| 264 | + size += sizeOfResults(node.getResults()); |
| 265 | + return size; |
| 266 | + } finally { |
| 267 | + releaseDeduplicatedObjectSet(deduplicatedObjects); |
| 268 | + } |
258 | 269 | } |
259 | 270 |
|
260 | 271 | private static long sizeOfInsertRowsOfOneDeviceNode(final InsertRowsOfOneDeviceNode node) { |
261 | 272 | final Set<Object> deduplicatedObjects = |
262 | | - newDeduplicatedObjectSetIfNeeded(node.getInsertRowNodeList()); |
263 | | - long size = INSERT_ROWS_OF_ONE_DEVICE_NODE_SIZE; |
264 | | - size += calculateFullInsertNodeSize(node, deduplicatedObjects); |
265 | | - size += sizeOfInsertRowNodeList(node.getInsertRowNodeList(), deduplicatedObjects); |
266 | | - size += sizeOfIntegerList(node.getInsertRowNodeIndexList()); |
267 | | - size += sizeOfResults(node.getResults()); |
268 | | - return size; |
| 273 | + acquireDeduplicatedObjectSetIfNeeded(node.getInsertRowNodeList()); |
| 274 | + try { |
| 275 | + long size = INSERT_ROWS_OF_ONE_DEVICE_NODE_SIZE; |
| 276 | + size += calculateFullInsertNodeSize(node, deduplicatedObjects); |
| 277 | + size += sizeOfInsertRowNodeList(node.getInsertRowNodeList(), deduplicatedObjects); |
| 278 | + size += sizeOfIntegerList(node.getInsertRowNodeIndexList()); |
| 279 | + size += sizeOfResults(node.getResults()); |
| 280 | + return size; |
| 281 | + } finally { |
| 282 | + releaseDeduplicatedObjectSet(deduplicatedObjects); |
| 283 | + } |
269 | 284 | } |
270 | 285 |
|
271 | 286 | private static long sizeOfInsertMultiTabletsNode(final InsertMultiTabletsNode node) { |
272 | 287 | final Set<Object> deduplicatedObjects = |
273 | | - newDeduplicatedObjectSetIfNeeded(node.getInsertTabletNodeList()); |
274 | | - long size = INSERT_MULTI_TABLETS_NODE_SIZE; |
275 | | - size += calculateFullInsertNodeSize(node, deduplicatedObjects); |
276 | | - size += sizeOfInsertTabletNodeList(node.getInsertTabletNodeList(), deduplicatedObjects); |
277 | | - size += sizeOfIntegerList(node.getParentInsertTabletNodeIndexList()); |
278 | | - size += sizeOfResults(node.getResults()); |
279 | | - return size; |
| 288 | + acquireDeduplicatedObjectSetIfNeeded(node.getInsertTabletNodeList()); |
| 289 | + try { |
| 290 | + long size = INSERT_MULTI_TABLETS_NODE_SIZE; |
| 291 | + size += calculateFullInsertNodeSize(node, deduplicatedObjects); |
| 292 | + size += sizeOfInsertTabletNodeList(node.getInsertTabletNodeList(), deduplicatedObjects); |
| 293 | + size += sizeOfIntegerList(node.getParentInsertTabletNodeIndexList()); |
| 294 | + size += sizeOfResults(node.getResults()); |
| 295 | + return size; |
| 296 | + } finally { |
| 297 | + releaseDeduplicatedObjectSet(deduplicatedObjects); |
| 298 | + } |
280 | 299 | } |
281 | 300 |
|
282 | 301 | private static long sizeOfRelationalInsertRowsNode(final RelationalInsertRowsNode node) { |
283 | 302 | final Set<Object> deduplicatedObjects = |
284 | | - newDeduplicatedObjectSetIfNeeded(node.getInsertRowNodeList()); |
285 | | - long size = RELATIONAL_INSERT_ROWS_NODE_SIZE; |
286 | | - size += calculateFullInsertNodeSize(node, deduplicatedObjects); |
287 | | - size += sizeOfInsertRowNodeList(node.getInsertRowNodeList(), deduplicatedObjects); |
288 | | - size += sizeOfIntegerList(node.getInsertRowNodeIndexList()); |
289 | | - // ignore deviceIDs |
290 | | - return size; |
| 303 | + acquireDeduplicatedObjectSetIfNeeded(node.getInsertRowNodeList()); |
| 304 | + try { |
| 305 | + long size = RELATIONAL_INSERT_ROWS_NODE_SIZE; |
| 306 | + size += calculateFullInsertNodeSize(node, deduplicatedObjects); |
| 307 | + size += sizeOfInsertRowNodeList(node.getInsertRowNodeList(), deduplicatedObjects); |
| 308 | + size += sizeOfIntegerList(node.getInsertRowNodeIndexList()); |
| 309 | + // ignore deviceIDs |
| 310 | + return size; |
| 311 | + } finally { |
| 312 | + releaseDeduplicatedObjectSet(deduplicatedObjects); |
| 313 | + } |
291 | 314 | } |
292 | 315 |
|
293 | 316 | private static long sizeOfRelationalInsertRowNode(final RelationalInsertRowNode node) { |
@@ -775,8 +798,24 @@ private static Set<Object> newDeduplicatedObjectSet() { |
775 | 798 | return Collections.newSetFromMap(new IdentityHashMap<>()); |
776 | 799 | } |
777 | 800 |
|
778 | | - private static Set<Object> newDeduplicatedObjectSetIfNeeded(final List<?> children) { |
779 | | - return children != null && children.size() > 1 ? newDeduplicatedObjectSet() : null; |
| 801 | + private static Set<Object> acquireDeduplicatedObjectSetIfNeeded(final List<?> children) { |
| 802 | + return children != null && children.size() > 1 ? REUSABLE_DEDUPLICATED_OBJECTS.get() : null; |
| 803 | + } |
| 804 | + |
| 805 | + private static void releaseDeduplicatedObjectSet(final Set<Object> deduplicatedObjects) { |
| 806 | + if (deduplicatedObjects == null) { |
| 807 | + return; |
| 808 | + } |
| 809 | + final boolean oversized = deduplicatedObjects.size() > MAX_RETAINED_DEDUPLICATED_OBJECTS; |
| 810 | + deduplicatedObjects.clear(); |
| 811 | + if (oversized) { |
| 812 | + REUSABLE_DEDUPLICATED_OBJECTS.remove(); |
| 813 | + } |
| 814 | + } |
| 815 | + |
| 816 | + @TestOnly |
| 817 | + static void clearReusableDeduplicatedObjectsForTest() { |
| 818 | + REUSABLE_DEDUPLICATED_OBJECTS.remove(); |
780 | 819 | } |
781 | 820 |
|
782 | 821 | private static boolean shouldCountObject( |
|
0 commit comments