Repository navigation
Conversation
Provide an alternative to the per-batch C Data handoff in PR apache#103 while retaining PyO3 0.28.3. Add ownership, buffer-sharing, compatibility, and public client handoff tests. Generated-by: OpenAI Codex
Apply LC's suggestion to export one boxed RecordBatchReader through arrow-pyarrow and materialize it with read_all. Remove the custom stream callbacks, unused converter crate, and dedicated converter workflow. Keep schema consistency checks, standalone schema preflight, and the NUL schema IPC fallback. Retain handoff tests in the coverage workflow and keep PyO3 at 0.28.3. Generated-by: OpenAI Codex (application version unavailable).
Keep public behavior coverage and compile mock protocol descriptors from source. Add native toArrow smoke cases, remove the unproven schema preflight, and avoid the arrow module name collision. Leave CI workflows unchanged. Co-authored-by: Isaac <no-reply@databricks.com>
Document the Arrow 58.3 NUL export panic at its upstream source and wrap the architecture paragraph. Keep CI workflows unchanged. Co-authored-by: Isaac <no-reply@databricks.com>
…am interface Normalize Arrow schemas and timestamps with the existing PySpark helpers, then serialize imported Rust batches directly for local relations without Python row materialization. Co-authored-by: Isaac <no-reply@databricks.com>
Honor server local-relation settings, split Arrow IPC into independently readable chunks, and upload session-scoped cache artifacts with SHA-256 deduplication and CRC validation. Keep large input payloads out of query plans and test uploads above the gRPC message limit. Co-authored-by: Isaac <no-reply@databricks.com>
… pandas input Authenticate concrete datetime storage and native schema/converter access before selecting the columnar path. Reject nonnullable NaT locally before requesting timezone configuration and keep local converter imports compatible. Co-authored-by: Isaac <no-reply@databricks.com>
…mantics Use explicit LongType schema names when constructing Arrow columns. Limit the columnar path to concrete pandas/NumPy arrays and native schema descriptors, including authentic converter aliases retained by already imported modules. Keep nullable values in non-nullable fields on the native row path so local validation still precedes configuration RPCs. Support warm Arrow importers that resolve converters locally. Add mock-RPC regressions for all emitted integer cells, schema metadata and nullability, custom conversion hooks, and repeated warm construction. Co-authored-by: Isaac <no-reply@databricks.com>
Build the subclass-label fallback fixture with an explicit object Index and assert its concrete label type. Pandas 3 otherwise normalizes constructor labels to builtin strings before the unchanged integer helper sees them. The original regression passes on pandas 2.3.3 and fails on 3.1.0; the fixed regression and full CI-selected Arrow/drop-in suites pass on both versions. Runtime Python and native sources remain unchanged. Co-authored-by: Isaac <no-reply@databricks.com>
Merge current Apache master d9defae while retaining all pandas integer input guards and the pandas 3 fixture repair. Keep upstream Arrow output regressions, CI protoc requirement and live smoke step; preserve fork input bridge/docs and stable-buffer assertions. Co-authored-by: Isaac <no-reply@databricks.com>
Reconcile the merged Arrow export master without rewriting the pandas timestamp branch. Retain every timestamp eligibility and pandas input regression, plus the final upstream output guards, stable-buffer and CI protoc checks. Co-authored-by: Isaac <no-reply@databricks.com>
Decline noncanonical columns indexes and their direct string-storage hooks before the integer fast path inspects labels or normalizes cells. Keep native tolist errors and mutations in their original order and cover public construction on both pandas versions. Co-authored-by: Isaac <no-reply@databricks.com>
Decline class-level columns storage descriptors before reading labels. Keep the single native columns storage read before pandas normalization, and cover public construction with inferred, named and explicit schemas on both pandas versions. Co-authored-by: Isaac <no-reply@databricks.com>
Co-authored-by: Isaac <no-reply@databricks.com> # Conflicts: # python/tests/test_arrow_handoff.py
Decline customized pandas Index conversion and storage before timestamp eligibility reads labels. Keep native row conversion and errors in order. Cover public columns hooks, storage descriptors and ordinary ns/us labels. Co-authored-by: Isaac <no-reply@databricks.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changes
createDataFramematerializes supported pandas timestamps as Python objects and converts each value separately. This PR hands explicitTimestampTypecolumns to the existing Arrow importer when every column isdatetime64[ns]or[us]and all values are microsecond-aligned. It preserves aware instants; naive timestamps require an actual UTC process (TZ=UTC) and UTC session. Explicit names, metadata, nullability andNaTare preserved. NonnullableNaTfails locally before timezone configuration, including when Config is unavailable.Eligibility requires authentic pandas DataFrame/Series/datetime storage, native schema access and converter aliases. The latest followup also checks canonical column-label storage before timestamp eligibility reads the labels. Customized
tolist, label descriptors and string-storage hooks retain native row conversion, including hook effects, exceptions and call order. Ordinary NumPy, Python-string and Arrow-string labels remain eligible. The timestamp-specific product change is the shared two-line canonical-column guard; public regressions exercisecreateDataFramedelivery and errors rather than private eligibility assertions.Inference, names/DDL schemas,
TimestampNTZ, mixed/object/Arrow extension dtypes, other units, empty frames, submicrosecond values and unsupported naive timezones retain the row fallback. Timestamp helpers use local native schema imports and support importers that resolve converters locally.Source and dependency scope
Final candidate:
7b53529d261b190130f36cf0a28070e5ea2de206. It descends from the previously published PR130 head4b92da42bd765b812052a3ec116b2d006789b78d, normally merges the reviewed PR121 integer dependencyc4284a3e0b71c8d624a1253c52337419761b2131, then adds the timestamp column-label guard and its regressions. The dependency supplies the shared canonical-label helper and integer hook/storage fixes; its Python regressions are consolidated into the existing Arrow CI test suite. This PR depends on #121 and transitively #118. #108 has merged upstream.The matched guard baseline is
6312f39dec1bb6cd083650fc7fd2570c4f708bde, which separately merges that same exactc4284a3dependency into4b92da4. The new paired costs isolate the timestamp guard with this dependency present on both sides. They do not measure the complete published4b92da4→ final-candidate change. The only product difference between these matched sources is the guard; their other difference is the new public tests. Historical speedups below retain their original source/environment scope and are not replaced by these guard-cost measurements.Current candidate validation
Both independently built sources pass formatting, 394 client Rust unit tests, 95 core Rust unit tests, and compilation of every native and WASM test target. The complete Python inventory is
test_dropin_offline.py,test_arrow_handoff.pyandtest_arrow_e2e.py:The two baseline failures common to both versions are explicit integer
_dataread-order cases: the unguarded timestamp eligibility path reads labels before row normalization. The additional two pandas 3.1 failures preserve values/nulls/schemas and zero Config RPC but fail exact string-backingto_numpymutation order. The candidate fixes all four. A first baseline invocation mistakenly named nonexistenttest_pandas_input.pyand exited 4 without running tests; that failed invocation and all subsequent expected baseline failures are preserved separately. Passing native builds from that attempt were retained.The candidate adds 20 public negative cases and 12 canonical-storage positive cases. Independent standalone probes pass 20/20 on both pandas versions, as does an explicit native-row control. The unguarded baseline passes 2/20 and fails the other 18 semantically, with zero setup failures: eight raising
tolisthooks bypassed, eight mutating hooks bypassed, and two_dataorder failures. The two_valuesprobes already pass on the baseline and establish no regression sensitivity. Every successful delivery checks all 10,000 values/nulls and complete physical and logical schemas.Fresh release wheels are source-bound to all 259 Python modules and the installed native extension in four isolated Rust environments, with exact executable/prefix, imports/spec origins, direct URL and dependency checks. Wheel SHA256: baseline
925a238c54a59872a93ed85665e50e5c620db15241a3b1b979986ddaa95f101a; candidatea10d8ecbaf78793466618b57213558934e96ad730f8a52afe0eaafe07bed4a2e. Both native binaries are byte-identical:9ef8c0accbafc7fb1f7c1b2bc76201e4c20957c30ce2bc270f3d45fb4fca56fe.Matched timestamp-guard costs and correctness
All 540 final samples passed: 300 main samples plus 240 focused samples, five per role/case/profile. The pandas 2.3 main catalog uses the original 13 warm cases × three clients, plus three first-construction guards × three clients. The pandas 3.1 main supplement uses the Rust pair for three cases and both profiles. Focused supplements cover ns/us accepted input, a representative instance mutation fallback and an expected hook error on both pandas versions/profiles.
Independent saved-byte review reconstructs all 430 received IPC requests / 12,400,000 cells, including complete typed values/nulls, payload hashes and full physical/logical schemas; it also verifies 80 expected-error receipts and 30 frozen return samples. All 46 case/profile comparisons have identical complete 20-counter RPC maps at each paired sample index (230 matched RPC-map pairs). This equality does not mean every case has zero RPCs: accepted timestamps can request Config; all measured error counters are zero.
The final costs show observable guard costs and noise. For example, pandas 2.3 warm timestamp wall median is 2.121 → 2.342 ms and CPU 1.183 → 1.479 ms; pandas 3.1 first timestamp wall is 4.149 → 4.766 ms and CPU 2.539 → 2.965 ms. The warm pandas 2.3 string, array and date wall/CPU medians also increase. The largest positive held/sampled-peak/process-peak RSS median difference is +1.562 MiB for warm pandas 2.3 strings; its post-GC difference is +1.188 MiB. All measured wall/CPU ranges and every positive RSS median movement are disclosed below. There is no latency-neutral, memory-neutral or zero-overhead claim.
Measurement boundaries and limits:
1bbdec9f3665fcd2ec2ee5129bbcdb95ee4b00c4; original main operations, timing boundaries, validators and RSS sampler are unchanged. Additive proof and explicit focused fixtures are separately preserved. Builds/tests/measurements ran serially under the campaign lock and an inner deadline guard.pyspark-client 5.0.0.dev0from Apache Spark sourceca1514a2b4e72f9529871f34d09881cd4921df82, pandas 2.3.3, NumPy 2.5.4, PyArrow 26.0.0, grpcio 1.84.1 and psutil 7.2.2. Its actual runtime proof checks all 366 Python modules, executable/prefix, direct URL and import origins. There is no official pandas 3.1 timed comparison; the prior official pandas 3.1 timeout is unresolved and preserved.clean_cacheExecutePlan requests overwrote all 14 original official input capture files. Those original 636,000 cells cannot be reconstructed from the old raw bytes; only 72 original captures / 1,844,000 cells remain reconstructable. Original receipts/results/failures are preserved. An additive untimed immutable request copy was reviewed before final execution. A separate fresh official-only 11-warm + three-first proof supplement passes 14/14 and validates 636,000 cells, with hashes checked after worker exit/cleanup. It does not recover the original lost bytes or establish paired performance. No successful Rust/focused preflight workload was repeated.All 46 final wall and CPU distributions, including adverse movements
Each value is median[min,max] of five fresh samples.
Bis the matched Rust baseline;Nis the same-install native-row control. All units are milliseconds except expected-error rows, which use microseconds. Official wall is shown only where an official process was timed. Role medians are not medians of the paired sample differences; overlapping ranges do not establish neutrality or significance.main / pandas 2.3 / warm
main / pandas 2.3 / first-construction
main / pandas 3.1 Rust pair / warm
main / pandas 3.1 Rust pair / first-construction
focused / pandas 2.3 / warm
focused / pandas 2.3 / first-construction
focused / pandas 3.1 / warm
focused / pandas 3.1 / first-construction
Every positive RSS median movement, with both role ranges
MiB; each role is median[min,max], followed by candidate minus control role-median difference. Setup = baseline RSS before the operation; H = held RSS; S = sampled peak; P = process peak; G = post-GC RSS. H/S/P are combined only where both roles have identical complete five-sample distributions for those metrics. This table includes all positive role-median differences, however small; negative/zero movements and full same-index paired distributions are retained in the machine-readable results. These are absolute process values; varying setup RSS and overlapping ranges limit allocation attribution. Post-GC includes proof allocations.
main / pandas 2.3 / warm
main / pandas 2.3 / first-construction
main / pandas 3.1 Rust pair / warm
main / pandas 3.1 Rust pair / first-construction
focused / pandas 2.3 / warm
focused / pandas 2.3 / first-construction
focused / pandas 3.1 / warm
focused / pandas 3.1 / first-construction
Frozen evidence identity
The final report and independent raw audit bind the exact candidate and matched baseline above.
cost-distributions.jsonretains all 322 paired seven-metric distributions, every raw value/range, same-index paired differences and complete RPC maps. The CSV and report are derived from those retained sample artifacts.source-finalization.jsond0fff116a3b03a73188a0549ece61bf2cbbb0bf5c78bb9d272e13ceef1c45bb6_pandas_input.py976123c5acfd2fa1ecbf6277b8ab18dbd9a824252c8f77dbfd489357ad403e72test_arrow_handoff.py3efc940bd2af4a4f1517ed5d1cfd0e26b76f4e0cfde74c9e58f388dca79bb7ffcost-distributions.json58d046685493bedb4b38cae81e9fbb4028b966812142e1ce9a4483b6ceaaae65cost-summary.csv8c403b52ade81c9fc32c2d71985c6c5c04c64bb851edc94cb4363d2d8578983aREPORT.md84cc0c0bad2f8f87da165461e72160b3d3c38802ef85f2678754eb7b8c3db992c2ec22809749d6ab33f5e27b477b4c9f8c07fbc02d7a638febee7bf37655d4034e5b05bc29bd1742c71d686bab97f3432c495e2917a0d4f1cae4ce693d9f2040Historical performance and protocol evidence
These results belong to the revisions specified here. They establish the original timestamp path's benefit and earlier eligibility behavior; they are not new measurements of the final candidate, its dependency merge, or the complete published-head-to-candidate change.
Initial timestamp implementation
Candidate
979fadc8d2aba3dad757641f81973afa62aa7ab6versus identical PR121 dependency baselinea8774f0bc8289856b98d11ddbb6b0c0aff95eaee, frozen harness1bbdec9f3665fcd2ec2ee5129bbcdb95ee4b00c4, official sourceca1514a2b4e72f9529871f34d09881cd4921df82:979fadc8That source measured 29.4× faster than the identical PR121 baseline. Constructor validation was unchanged; decoded IPC established correctness independently. The original 13-case × three-client × five-sample run passed 195/195; a further ten-sample integer guard passed 30/30. The small 1,000-row integer guard initially moved +0.159 ms (+12.2%); the followup measured 1.495 → 1.354 ms, with overlapping ranges in both runs. Raw noisy samples are retained. Candidate wheel SHA256
705cfe0787f713fb6dbd9dfe6d7ad2db4f00778ae4ed22f8ef5c50d762c3981f; baselinee6a84acc30979fa171ef94bbdc2b575ae4f0ac70579e3282f27337603193c879.At that source, 394 Rust library tests passed, all workspace release/locked test targets compiled, and 366 Python tests passed with nine existing skips. Independent official/baseline/candidate processes verified 17 complete-IPC scenarios per client: UTC/non-UTC host/session zones, aware/naive values, DST folds/transitions,
NaT, negative/boundary values, precision and schema fallbacks.Earlier eligibility followup
Candidate
5f31a4c012300e7f18c17829223102a186084fefretained original PR121 dependencya8774f0on both measured Rust sides. Its 63 bounded samples passed: timestamp baseline 60.276 → candidate 2.144 ms (28.1×), official 1.255 ms. Against prior PR130979fadc8, it measured 2.438 → 2.189 ms with overlapping ranges. Integer/fallback/Arrow input/Arrow return guard ranges also overlapped. Its wheel SHA256 is1effffcc6eef70fdec891757d29c142f4ab68d756e092ac79c09a96626dc29ea.At that source, 443 Python tests passed with nine existing skips; native/WASM test targets compiled and native bytes remained unchanged. Reference/prior/followup processes passed 17 full-IPC scenarios each (51 runs), checking every timestamp/null, physical name/type/nullability and complete logical metadata. Candidate/prior physical schemas were byte-identical; the permitted official difference was redundant Arrow metadata encoding. The public converter-alias regression failed on the prior wheel as expected. Tests also covered custom datetime storage, schema descriptors, captured converter aliases, pre-Config null errors and local converter imports.
Previously published upstream reconciliation
A normal merge of upstream
d9defae6f691671d8bad4927f58a7283cd0a0b50into5f31a4cproduced published PR1304b92da42bd765b812052a3ec116b2d006789b78d, retaining the input implementation byte for byte and bringing upstream workflow/docs, an exporter comment and handoff guards. No timing rerun was claimed for that reconciliation. Fresh source/wheel checks passed 394 client / 95 core Rust units, all native/WASM test-target compilation, and 451 Python tests / 11 skips on each pandas 2.3.3 and 3.1.0. Wheel SHA25633f3a7bb5bb0993891cfa7f2406d915d408d5247c29fd37e53b868ef2f0592a0; all 259 source/wheel/installed Python modules matched and native bytes remained identical. Two restricted-sandbox attempts failed unchanged bearer-metadata TLS setup; a retained same-source run with normal system test access passed that test and the full core suite. No certificate/authentication/configuration changes were made.Known fallback limits
The supported columnar path matches official reference microseconds at boundaries where the old pandas-object/datetime path and floating timestamp rounding lose precision, including a lower-bound ns sign/wrap case. Unsupported row fallbacks preserve pre-existing differences: naive timestamps use the host zone rather than the session zone, DST overlap/gap behavior differs, and -1 ns truncation differs. This PR does not extend those fallback semantics.
JIRA: https://issues.apache.org/jira/browse/SPARK-60686
This pull request and its description were written by Isaac.