Skip to content

PERF: GIL-free loop, fixed-layout fast path and same-date cache for the read_csv parse_dates fastpath#66278

Draft
jbrockmendel wants to merge 13 commits into
pandas-dev:mainfrom
jbrockmendel:perf-read_csv-datetimes-nogil
Draft

PERF: GIL-free loop, fixed-layout fast path and same-date cache for the read_csv parse_dates fastpath#66278
jbrockmendel wants to merge 13 commits into
pandas-dev:mainfrom
jbrockmendel:perf-read_csv-datetimes-nogil

Conversation

@jbrockmendel

Copy link
Copy Markdown
Member

Draft, stacked on GH-65353 (branched from perf-read_csv-datetimes; the diff shows that PR's commits until it merges — only the top commit is new).

The per-row loop in _datetime_box_utf8 is now pure C and runs without the GIL (the prerequisite for parallelizing parse_dates reads as a follow-up to GH-66275). The two dominant fixed-width layouts (YYYY-MM-DD and YYYY-MM-DD[ T]HH:MM:SS) parse through a dedicated validator instead of the general ISO parser, consecutive timestamps sharing a calendar date reuse the date's epoch conversion, and format-consistency checks between fixed-layout rows collapse to an O(1) layout-code comparison. The receipts/all-or-nothing fallback semantics of the base PR are preserved; get_supported_reso becomes noexcept nogil in tslibs.

Benchmark vs the base branch (M3 Pro, 1M rows × 4 ISO datetime columns, parse_dates, serial, interleaved A/B): 291.3 → 133.6 ms (−54%).

🤖 Generated with Claude Code

jbrockmendel and others added 11 commits April 23, 2026 18:45
For columns named in parse_dates, the C tokenizer now parses each
ISO8601 field from its char buffer straight into a datetime64 output,
skipping the intermediate ndarray[object] of Python strings that
date_converter would otherwise feed to to_datetime. Naive and tz-aware
inputs with consistent offsets are handled, mixed resolutions trigger
a single recursive reparse at the widest unit, and any non-ISO or
mixed-offset column falls back to the existing object-string path.

Benchmarks at 500k rows: ISO naive 222ms -> 88ms, tz-aware 167ms -> 62ms.
Non-ISO formats are unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- require a consistent format when date_format is None, matching
  to_datetime's infer-from-first-element behavior; mixed ISO layouts
  parse per-row only with date_format="ISO8601"
- in low_memory mode, keep raw-byte receipts per chunk so a fallback in
  any chunk restores the whole column to the object-string path
  (previously parsed chunks could be silently re-stringified from
  Timestamps when a later chunk fell back)
- guard the tz-to-UTC shift against int64 wraparound near the
  datetime64 bounds; fall back so the slow path raises as before
- fall back on all-NA columns so the dtype matches the slow path
- skip marking implicit-index files; noconvert indices cannot line up
- tests

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…imes

# Conflicts:
#	doc/source/whatsnew/v3.1.0.rst
# Conflicts:
#	doc/source/whatsnew/v3.1.0.rst
#	pandas/_libs/parsers.pyx
# Conflicts:
#	doc/source/whatsnew/v3.1.0.rst
# Conflicts:
#	doc/source/whatsnew/v3.1.0.rst
_box_arena_utf8 referenced kh_get_strbox (not in the khash cimport list)
and PyUnicode_Decode (not imported); both were undeclared-name Cython
errors. Add the cimport and switch to the already-imported
PyUnicode_DecodeUTF8 helper.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
# Conflicts:
#	pandas/_libs/parsers.pyx
…he parse_dates fastpath

The per-row loop in _datetime_box_utf8 is now pure C and runs without
the GIL, so parse_dates columns convert in parallel in the threaded
read path. The two dominant fixed-width layouts (YYYY-MM-DD and
YYYY-MM-DD[ T]HH:MM:SS) parse through a dedicated validator instead of
the general ISO parser, consecutive timestamps sharing a calendar date
reuse the date's epoch conversion, and format-consistency checks
between fixed-layout rows collapse to an O(1) layout-code comparison.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jbrockmendel jbrockmendel added Performance Memory or execution speed performance IO CSV read_csv, to_csv labels Jul 10, 2026
…imes

# Conflicts:
#	doc/source/whatsnew/v3.1.0.rst
#	pandas/_libs/parsers.pyx
…ogil

# Conflicts:
#	pandas/_libs/parsers.pyx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

IO CSV read_csv, to_csv Performance Memory or execution speed performance

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant