Skip to content

Add missing fast path for DateTime format "G"#129374

Open
danmoseley wants to merge 1 commit into
dotnet:mainfrom
danmoseley:runtime-dtfmt-modified
Open

Add missing fast path for DateTime format "G"#129374
danmoseley wants to merge 1 commit into
dotnet:mainfrom
danmoseley:runtime-dtfmt-modified

Conversation

@danmoseley

@danmoseley danmoseley commented Jun 14, 2026

Copy link
Copy Markdown
Member

Adds a fast path for DateTime.ToString("G", CultureInfo.InvariantCulture) similar to existing single-char fast path that 'o', 'r', 's', and 'u' already have in DateTimeFormat.Format / TryFormat<TChar>, and identical to the one the null/empty-format case (dt.ToString(CultureInfo.InvariantCulture)) already takes via TryFormatInvariantG.

The fast path is gated by offset.Ticks == NullOffset && ReferenceEquals(dtfi, DateTimeFormatInfo.InvariantInfo), so DateTimeOffset.ToString("G", InvariantCulture) and any custom/cloned DateTimeFormatInfo fall through to the existing pattern-based path unchanged.

Perf Results

5.5x faster

ResultsComparer, threshold 1%, noise 1 ns, 5 launches × 15 iterations × 16384 invocations, P-core pinned on i9-14900K:

summary: better: 1, geomean: 5.511, total diff: 1
No Slower results for the provided threshold = 1% and noise filter = 1 ns.
Faster base/diff Base Median (ns) Diff Median (ns)
System.Tests.Perf_DateTime.ToStringInvariant(format: "G") 5.51 41.58 7.54

The remaining 19 Perf_DateTime.ToString* cases (other formats, current-culture, DateTimeOffset) are unchanged. Allocation unchanged everywhere.

ToStringInvariant(format) is a new benchmark in Perf_DateTime.cs that calls date.ToString(format, CultureInfo.InvariantCulture).

Tests

Output is byte-identical to the slow path for DateTime + invariant culture ("MM/dd/yyyy HH:mm:ss", 19 chars). Existing DateTime / DateTimeOffset formatting tests pass. In addition, an ad-hoc correctness harness compared baseline vs. modified outputs over 10 DateTimes (incl. MinValue, MaxValue, year 1, year 9999, Feb 29 2000, all DateTimeKinds) × 5 cultures × 16 formats × {ToString, TryFormat} plus DateTimeOffset equivalents — 1040 byte-identical outputs. Separately verified TryFormat with too-small destinations (sizes 0..20 char, 0..25 UTF-8), composite formatting $"{dt:G}", cloned DTFI, and DTFI with customized LongTimePattern — all behave identically to baseline.

Note

This PR description was drafted by GitHub Copilot.

Mirrors the existing single-char fast paths for 'o', 'r', 's', 'u' and the null/empty-format invariant fast path that ToString(InvariantCulture) already uses, routing through TryFormatInvariantG instead of FormatCustomized. Output is byte-identical to the existing pattern-based path ("MM/dd/yyyy HH:mm:ss", 19 chars). ~5.5x faster (41.58 ns -> 7.54 ns median).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-datetime
See info in area-owners.md if you want to be subscribed.

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

Adds an invariant-culture fast path for the standard "G" format when formatting a DateTime (i.e., offset.Ticks == NullOffset) by directly using the existing TryFormatInvariantG implementation. This aligns "G" with the existing single-character fast paths (e.g., "o", "r", "s", "u") and the already-existing null/empty-format invariant fast path.

Changes:

  • Add a "G" switch case in DateTimeFormat.Format that fast-paths DateTime.ToString("G", InvariantCulture) to TryFormatInvariantG.
  • Add the corresponding "G" fast path in DateTimeFormat.TryFormat<TChar> for invariant culture + DateTime (NullOffset) scenarios.
Show a summary per file
File Description
src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs Adds an invariant "G" fast path in both Format and TryFormat<TChar> using TryFormatInvariantG when offset is NullOffset.

Copilot's findings

  • Files reviewed: 1/1 changed files
  • Comments generated: 0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants