Conversation
jt2594838
left a comment
There was a problem hiding this comment.
Implementation rationale and compatibility notes for the submitted changes. Focused tests and benchmark limitations are summarized in the PR description.
| } else { | ||
| row[c] = extractValue(vec, r); | ||
| } | ||
| Object[][] columns = new Object[numCols][rowCount]; |
There was a problem hiding this comment.
Build SourceBatch columns directly because both Arrow and the destination are columnar. Resolving each vector once removes repeated name lookups and the intermediate row arrays/transpose; absent vectors remain null. Existing Arrow reader tests and the cross-version output checks passed.
| } else if (vec instanceof VarBinaryVector) { | ||
| return ((VarBinaryVector) vec).get(row); | ||
| /** Select the physical vector type once for the entire column. */ | ||
| private void readColumn(FieldVector vec, Object[] output) { |
There was a problem hiding this comment.
Bind the physical vector type before iterating through its values. Each typed loop retains null checks, native timestamp precision, date conversion, UTF-8 decoding, and the generic fallback, while avoiding an instanceof chain for every cell.
|
|
||
| for (long r = 0; r < rowCount; r++) { | ||
| int count = Math.toIntExact(rowCount); | ||
| Object[][] columns = new Object[numCols][count]; |
There was a problem hiding this comment.
Keep the Parquet record reader row-oriented but write directly to the final column arrays. Column indices and extractors are resolved once per batch; missing or malformed fields retain the existing null behavior. This removes the row transpose without changing the input reader protocol.
| } | ||
|
|
||
| private Object extractValue(Group group, int fieldIndex) { | ||
| private Function<Group, Object> valueExtractor(int fieldIndex) { |
There was a problem hiding this comment.
Choose physical/logical-type conversion once per column, including the dedicated INT96 accessor, rather than inspecting schema metadata for every value. The wrapper still checks field presence per row. Local benchmarks showed lower allocation but inconclusive elapsed-time changes for Parquet.
| for (int col = 0; col < tableSchema.getColumnSchemas().size(); col++) { | ||
| IMeasurementSchema colSchema = tableSchema.getColumnSchemas().get(col); | ||
| String colName = colSchema.getMeasurementName(); | ||
| Type type = Type.fromTsDataType(colSchema.getType()); |
There was a problem hiding this comment.
Traverse columns after establishing sorted timestamps so schema lookup, the destination array, and type resolution are reused across rows. Direct insertion preserves Tablet bitmap semantics by unmarking only non-null converted values; tag defaults and sorted source indices retain their original behavior. Conversion is initialized lazily so empty/all-null columns do not invoke converters. The new tests compare this path with the public Tablet insertion API.
| } | ||
|
|
||
| @Test | ||
| public void testColumnConversionKeepsSortedRowsAndNulls() { |
There was a problem hiding this comment.
Mix strings and native values in a column with unsorted timestamps and null-format inputs. This specifically checks that a cached converter still chooses per-cell input handling and keeps tag defaults aligned with sorted rows.
|
|
||
| public class AlignedNullWriteTest { | ||
| @Test | ||
| public void tabletWriterCacheKeepsLateColumnPagesAndFailureOrder() throws Exception { |
There was a problem hiding this comment.
Compare cached Tablet writing with scalar writes while adding a column after earlier rows. Byte/page/statistics comparisons and a rejected timestamp guard both late-column catch-up and the order of validation versus writer creation.
| } | ||
|
|
||
| @Test | ||
| public void lateColumnsAndMissingRowsKeepPageBoundaries() throws Exception { |
There was a problem hiding this comment.
Force short pages, add every supported type after a sealed page plus a partial page, then write missing and present rows. Verify synchronized boundaries, null bitmaps, and value statistics so direct null appends cannot silently disturb alignment.
|
|
||
| public class TabletColumnWriteTest { | ||
| @Test | ||
| public void testEncodedPagesMatchScalarForAllTypes() throws Exception { |
There was a problem hiding this comment.
Compare sealed bytes, page counts, statistics, and accepted-point counts with scalar writing. The test covers all supported types, null masks, a nonzero source offset, both DATE arrays, and SDT settings for numeric types to guard encoding compatibility.
| } | ||
|
|
||
| @Test | ||
| public void testOutOfOrderKeepsWrittenPrefixAndSkipsNulls() throws Exception { |
There was a problem hiding this comment.
Verify that null rows do not trigger timestamp validation and that a later out-of-order row preserves the accepted prefix for a subsequent call. Long.MIN_VALUE, all-null ranges, null value arrays, and empty ranges exercise the context and early-exit boundaries.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## develop #963 +/- ##
===========================================
+ Coverage 63.95% 64.44% +0.48%
===========================================
Files 758 759 +1
Lines 53253 53299 +46
Branches 8445 8451 +6
===========================================
+ Hits 34060 34349 +289
+ Misses 17530 17288 -242
+ Partials 1663 1662 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Move type selection out of hot per-value loops in TsFile's read, write, and import paths. Pages and non-aligned Tablet columns use generated type-specific batch loops; aligned writes and query projections reuse resolved types. Arrow, Parquet, and TabletBuilder populate column arrays directly and resolve conversion metadata once per column.
The implementation preserves decoder consumption for filtered/deleted rows, pagination accounting, null bitmaps, late-column page alignment, scalar encoding/SDT behavior, and the successfully written timestamp prefix when an out-of-order row is rejected. Regression tests cover these boundaries, supported data types, and DATE representations.
Validation
PageDataBatchReaderTest,AlignedNullWriteTest,TabletColumnWriteTest,TabletBuilderTest,ValueConverterTest,ArrowSourceReaderTest, andParquetSourceReaderTest; the configured Maven lifecycle executed the selected suites twice, with no failures, errors, or skips.git diff --checkpassed.Benchmarks
Compared this branch at
5d15440e831dfeb00f025d8c78c716945cc250c2withdevelopat8fdbc49bc80eb4a4d6cf6e46cdf0cabd1a1c0837: JMH 1.37, Temurin 17.0.20.1, Windows 11, Intel i9-12900, one thread pinned to logical CPU 2, 512 MiB heap, 4096 rows, and 3 forks. Initial runs used 5 × 500 ms warmup and measurement iterations; six methods were repeated with 10 × 1 s warmup and 7 × 1 s measurement iterations, retaining both runs.Of 30 paired scenarios, 25 had lower measured time with separated intervals; five remain inconclusive. Parquet and single-destination scalar projection had overlapping intervals. Both
columnSelectedreruns were affected by unequal background load and are explicitly inconclusive, despite higher measured means. Other IoTDB workloads were active on the machine during extended runs, so these are shared-machine microbenchmark observations, not isolated causal estimates or end-to-end throughput claims. Interval separation is a conservative screening rule, not a paired statistical test.Benchmark sources, raw results, the detailed report, and reproduction commands remain local under
target/branch-vs-develop/, as requested, and are not part of this PR. The benchmark report's validation section describes the earlier benchmark phase; the focused unit tests above were run subsequently for PR submission.