Skip to content

FSharp.Core #if NET fast-path opportunities — SIMD / span / TensorPrimitives / formatting (unblocked by #20229) #20283

Description

@T-Gro

#20229 ships FSharp.Core with a net10.0 TFM. A #if NET8_0_OR_GREATER / #if NET block therefore compiles only into the net asset — netstandard2.0/netstandard2.1 stay bit-identical. This tracks the additive, guarded fast paths that unlocks.

Important gate distinction some span APIs are already in netstandard2.1, so FSharp.Core's ns2.1 asset could use them too — those are perf wins but not strictly gated on #20229.

Format per row: F# affectedFSharp.Core file:line.NET API → guard → win.

1 · Numeric reductions → SIMD TensorPrimitives (net-only)

F# affected FSharp.Core file .NET API guard win
Array.sum / Array.average array.fs:1628/1722 TensorPrimitives.Sum (net8) #if NET8_0_OR_GREATER 2–5× · gated: float reassociation; int drops Checked.(+) overflow
Array.max / Array.min array.fs:1685/1648 TensorPrimitives.Max/Min (net8) #if NET8_0_OR_GREATER 3–4× · gated: IEEE vs F# NaN — safe for ints
Seq.sum/average/min/max (array fast-path) seq.fs:1465/1485/1517/1557 TensorPrimitives behind :? ('T[]) (net8) #if NET8_0_OR_GREATER 2–4× · inherits above; array-backed only

2 · Primitive-array equality & comparison (ns2.1+)

F# affected FSharp.Core file .NET API guard win
GenericEquality{Byte,Int32,Int64,Char}Array prim-types.fs:1481/1496/1558/1543 MemoryExtensions.SequenceEqual<'T> `#if NETSTANDARD2_1_OR_GREATER
GenericComparisonByteArray prim-types.fs:1230 MemoryExtensions.SequenceCompareTo<byte> `#if NETSTANDARD2_1_OR_GREATER

3 · Array search & reorder (ns2.1+)

F# affected FSharp.Core file .NET API guard win
Array.contains (single primitive) array.fs:~488 MemoryExtensions.Contains / ReadOnlySpan.IndexOf `#if NETSTANDARD2_1_OR_GREATER
Array.rev array.fs:1386 System.Array.Reverse any TFM small

4 · Primitive-array hashing (net-only)

F# affected FSharp.Core file .NET API guard win
GenericHash{Byte,Int32,Int64}Array prim-types.fs:964/975/986 HashCode.AddBytes (net6) #if NET6_0_OR_GREATER 15–30% · keep in-process hash stability; 10-node cap

5 · String building (ns2.1+)

F# affected FSharp.Core file .NET API guard win
String.map / String.mapi / String.filter string.fs:57/71/89 String.Create(len, state, writer) `#if NETSTANDARD2_1_OR_GREATER

6 · Formatting / printf (mixed)

F# affected FSharp.Core file .NET API guard win
%O/%P/interpoland/user types/decimal/DateTime printf.fs:911–929 ObjectToString/InterpolandToString (+ span sink 1073–1083) ISpanFormattable.TryFormat (net6) + String.Create #if NET6_0_OR_GREATER skip 1 temp string per arg; polymorphic (no per-type match). No-width case first — padding is string-based today
numeric specifiers %d %i %u %x %X %f %e %g %M (no width/prec) printf.fs:746–770/852–859 concrete Int32/Int64/Double/Single/Decimal.TryFormat into Span<char> `#if NETSTANDARD2_1_OR_GREATER
StringBuilder / TextWriter sinks printf.fs:1073–1083 StringBuilder.Append(ReadOnlySpan<char>) / TextWriter.Write(ReadOnlySpan<char>) `#if NETSTANDARD2_1_OR_GREATER
sprintf string sink printf.fs:1029–1071 pooled char[] (ArrayPool) + String.Create `#if NETSTANDARD2_1_OR_GREATER

7 · Generic math (net-only)

F# affected FSharp.Core file .NET API guard win
GenericZero/OneDynamicImplTable (Half) prim-types.fs:2667/2700 typeof<System.Half> fast case (net5) #if NET5_0_OR_GREATER avoid reflection

No boost (documented negatives)

  • GenericEquality{Single,Double}Array (prim-types.fs:1511/1527) — NaN-reflexivity (er flag: NaN = NaN) diverges from IEEE SequenceEqual; keep scalar.
  • DefaultInterpolatedStringHandler as the printf sink — it is a ref struct, cannot be a field of the heap PrintfEnv class; and sprintf's ToStringAndClear() is itself just String.Create over a pool. DISH belongs to a compiler lowering.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions