Skip to content

Optimize DataSetWithoutTimeGenerator with primitive long heap/set - #906

Merged
hongzhi-gao merged 5 commits into
developfrom
optimize/dataset-without-time-generator-primitive-heap
Aug 17, 2026
Merged

Optimize DataSetWithoutTimeGenerator with primitive long heap/set#906
hongzhi-gao merged 5 commits into
developfrom
optimize/dataset-without-time-generator-primitive-heap

Conversation

@hongzhi-gao

@hongzhi-gao hongzhi-gao commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Optimize the multi-way merge hot path in DataSetWithoutTimeGenerator by replacing PriorityQueue<Long> / HashSet<Long> with trimmed, fastutil 8.5.8–derived primitive containers, avoiding autoboxing of timestamps and the related CPU/GC cost.

CPU profiles showed the hotspot on HashSet.containsHashMap.getNode via timeHeapPut, which is hit frequently in workloads such as Pipe extraction.

img_v3_0214g_8b329c57-96ab-4599-9fd7-6e86c133b31g

Changes

  • Add LongHeapPriorityQueue and LongOpenHashSet (forked from fastutil, APIs trimmed to what TsFile needs; key methods annotated with upstream origins)
  • Switch DataSetWithoutTimeGenerator to these containers, with capacity pre-sized by series count
  • Update root NOTICE for the fastutil-derived code and copyrights
  • Add regression tests:
    • DataSetWithoutTimeGeneratorTest: sparse multi-way merge and cross-batch continuation
    • LongOpenHashSetAndHeapPriorityQueueTest: heap/set correctness (including edge cases), parity vs boxed JDK collections, combined dedup-merge pattern, and a micro-benchmark

Performance results

Micro-benchmark of the same heap+set dedup-merge pattern used by DataSetWithoutTimeGenerator (50 series × 100,000 rows), comparing JDK PriorityQueue<Long>+HashSet<Long> with the primitive implementation:

Implementation Time Speedup
boxed (PriorityQueue + HashSet) ~40–55 ms 1.0x
primitive (LongHeapPriorityQueue + LongOpenHashSet) ~9 ms ~4.5x–6.0x

Notes: micro-benchmarks vary with machine load; local runs typically land around ~2x–6x. Absolute gain depends on series count and total points. Correctness tests vs boxed behavior all passed.

Test plan

  • mvn -pl tsfile test -Dtest=LongOpenHashSetAndHeapPriorityQueueTest,DataSetWithoutTimeGeneratorTest
  • Review fastutil fork scope and LICENSE compliance
  • (Optional) Re-profile IoTDB Pipe extraction and confirm the HashSet.contains hotspot shrinks

Replace PriorityQueue<Long>/HashSet<Long> with fastutil-derived
LongHeapPriorityQueue/LongOpenHashSet to avoid boxing on the
multi-way merge hot path. Update NOTICE and add regression tests.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR optimizes the multi-way merge hot path in DataSetWithoutTimeGenerator by replacing boxed timestamp containers (PriorityQueue<Long> / HashSet<Long>) with fastutil-derived primitive long heap/set implementations to reduce autoboxing overhead and GC pressure in query workloads.

Changes:

  • Introduces fastutil 8.5.8–derived primitive containers: LongHeapPriorityQueue and LongOpenHashSet.
  • Switches DataSetWithoutTimeGenerator to use the primitive heap/set, pre-sized by series count.
  • Adds NOTICE attribution and regression tests covering merge correctness, data-structure correctness, and a (currently unguarded) micro-benchmark.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
NOTICE Adds required attribution for fastutil-derived code.
java/tsfile/src/main/java/org/apache/tsfile/utils/LongOpenHashSet.java New primitive open-addressing long hash set (trimmed from fastutil).
java/tsfile/src/main/java/org/apache/tsfile/utils/LongHeapPriorityQueue.java New primitive long min-heap priority queue (trimmed from fastutil).
java/tsfile/src/main/java/org/apache/tsfile/read/query/dataset/DataSetWithoutTimeGenerator.java Replaces boxed heap/set with primitive implementations and pre-sizes them.
java/tsfile/src/test/java/org/apache/tsfile/read/query/dataset/DataSetWithoutTimeGeneratorTest.java Adds regression tests for sparse multi-way merge and cross-batch continuation.
java/tsfile/src/test/java/org/apache/tsfile/utils/LongOpenHashSetAndHeapPriorityQueueTest.java Adds correctness tests plus a micro-benchmark/perf smoke test for the new containers.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines 141 to 145
private void timeHeapPut(long time) {
if (!timeSet.contains(time)) {
timeSet.add(time);
timeHeap.add(time);
timeHeap.enqueue(time);
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, switched to if (timeSet.add(time)) to avoid the double probe.

Comment on lines +260 to +267
public void testPrimitiveStructuresPerformance() {
final int series = 50;
final int rows = 100_000;
final long baseTime = 1_700_000_000_000L;

runBoxed(series, 10_000, baseTime);
runPrimitive(series, 10_000, baseTime);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, gated with Assume.assumeTrue behind -Dtsfile.runPerformanceTests=true, same as other TsFile perf tests.

@codecov-commenter

codecov-commenter commented Aug 17, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.45455% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 60.71%. Comparing base (5681978) to head (17dcc8d).

Files with missing lines Patch % Lines
.../java/org/apache/tsfile/utils/LongOpenHashSet.java 93.91% 7 Missing ⚠️
...org/apache/tsfile/utils/LongHeapPriorityQueue.java 98.18% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop     #906      +/-   ##
===========================================
+ Coverage    60.60%   60.71%   +0.11%     
===========================================
  Files          745      747       +2     
  Lines        49508    49678     +170     
  Branches      7945     7979      +34     
===========================================
+ Hits         30002    30163     +161     
- Misses       18046    18055       +9     
  Partials      1460     1460              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread NOTICE Outdated
Comment on lines +23 to +29

============================================================================

This product includes code derived from fastutil (http://fastutil.di.unimi.it/):
Copyright (C) 2002-2022 Sebastiano Vigna
Copyright (C) 2003-2022 Paolo Boldi and Sebastiano Vigna
Licensed under the Apache License, Version 2.0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to add this

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

@ColinLeeo ColinLeeo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@hongzhi-gao
hongzhi-gao merged commit 7798b10 into develop Aug 17, 2026
38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants