From 0cb200fd5dbbae1bd942d5d3a87b7d1b54ffe5fd Mon Sep 17 00:00:00 2001 From: James Montemagno Date: Thu, 5 Feb 2026 11:12:19 -0800 Subject: [PATCH 01/11] Update libraries.md for Preview 1 --- release-notes/11.0/preview/preview1/libraries.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/release-notes/11.0/preview/preview1/libraries.md b/release-notes/11.0/preview/preview1/libraries.md index b46dccf969..6619bd38da 100644 --- a/release-notes/11.0/preview/preview1/libraries.md +++ b/release-notes/11.0/preview/preview1/libraries.md @@ -2,7 +2,13 @@ .NET 11 Preview 1 includes new .NET Libraries features & enhancements. -This Preview 1 release does not introduce new .NET Libraries features. +Here's a summary of what's new in .NET Libraries in this Preview 1 release: + +- [Feature](#feature) + +## Feature + +Feature summary. .NET Libraries updates in .NET 11: From a9bb3b75191790866f6842963742009eddb65327 Mon Sep 17 00:00:00 2001 From: Art Leonard Date: Thu, 5 Feb 2026 14:43:30 -0800 Subject: [PATCH 02/11] Revise release notes for .NET 11 Preview 1 libraries Updated release notes for .NET 11 Preview 1 libraries, summarizing new features, improvements, and notable changes across various feature areas. --- .../11.0/preview/preview1/libraries.md | 933 +++++++++++++++++- 1 file changed, 925 insertions(+), 8 deletions(-) diff --git a/release-notes/11.0/preview/preview1/libraries.md b/release-notes/11.0/preview/preview1/libraries.md index 6619bd38da..5f327d286f 100644 --- a/release-notes/11.0/preview/preview1/libraries.md +++ b/release-notes/11.0/preview/preview1/libraries.md @@ -1,15 +1,932 @@ -# .NET Libraries in .NET 11 Preview 1 - Release Notes +# What's New in .NET 11 Libraries (Preview 1) -.NET 11 Preview 1 includes new .NET Libraries features & enhancements. +This summarizes new features, performance improvements, and notable changes in .NET Libraries in .NET 11 Preview 1. -Here's a summary of what's new in .NET Libraries in this Preview 1 release: +## Feature Areas -- [Feature](#feature) +- [Threading & Time](#threading--time) (3) +- [Networking (HTTP)](#networking-http) (7) +- [Networking](#networking) (7) +- [Other](#other) (5) +- [Hardware Intrinsics](#hardware-intrinsics) (4) +- [File I/O](#file-i/o) (4) +- [Cryptography & Security](#cryptography-&-security) (3) +- [Runtime](#runtime) (3) +- [Memory](#memory) (3) +- [Regular Expressions](#regular-expressions) (2) +- [JSON Serialization](#json-serialization) (2) +- [Compression](#compression) (2) +- [Globalization](#globalization) (2) +- [System.Runtime.InteropServices.JavaScript](#systemruntimeinteropservicesjavascript) (2) +- [Buffers](#buffers) (2) +- [LINQ](#linq) (2) +- [Collections](#collections) (2) +- [System.Formats.Tar](#systemformatstar) (2) +- [Numerics](#numerics) (1) +- [Tensor Primitives](#tensor-primitives) (1) +- [Microsoft.Extensions.Logging](#microsoftextensionslogging) (1) +- [System.Diagnostics](#systemdiagnostics) (1) +- [System.Runtime.InteropServices](#systemruntimeinteropservices) (1) +- [System.Runtime.CompilerServices](#systemruntimecompilerservices) (1) -## Feature +--- -Feature summary. +## Networking (HTTP) -.NET Libraries updates in .NET 11: +### New Features + +#### Add DecompressionMethods.Zstandard for HTTP automatic decompression + +[PR #123531](https://github.com/dotnet/runtime/pull/123531) by @rzikm with GitHub Copilot + +Adds Zstandard compression support to DecompressionMethods for automatic HTTP response decompression, matching the API proposal. Follows the established pattern from Brotli support. + +```csharp +var handler = new HttpClientHandler +{ + AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Zstandard +}; + +using var client = new HttpClient(handler); +// Automatically decompresses zstd-encoded responses +var response = await client.GetAsync("https://example.com"); +``` + +#### Add an ASCII check for edge-case non-ASCII hosts that can't be Punycode encoded + +[PR #123934](https://github.com/dotnet/runtime/pull/123934) by @MihaZupan + +This is an edge-case where some hosts that exceed DNS limits (e.g. contain long labels) can't get Punycode encoded, and their IdnHost may return a non-ASCII value. + +#### Add support for socks5h proxy scheme + +[PR #123218](https://github.com/dotnet/runtime/pull/123218) by @MihaZupan with GitHub Copilot + +HttpClient now accepts socks5h:// proxy URIs. Previously, attempts to use this scheme threw NotSupportedException with message "Only the 'http', 'https', 'socks4', 'socks4a' and 'socks5' schemes are allowed for proxies." + +```csharp +using var handler = new SocketsHttpHandler(); +handler.Proxy = new WebProxy("socks5h://username:password@proxy.example.com:1080"); +using HttpClient client = new HttpClient(handler); +var response = await client.GetStringAsync("http://ifconfig.me/ip"); +``` + +### Improvements + +#### [browser] LoopbackServer - make GenericLoopbackServer.CloseWebSocket async + +[PR #123327](https://github.com/dotnet/runtime/pull/123327) by @pavelsavara + +[browser] LoopbackServer - make GenericLoopbackServer.CloseWebSocket async + +#### Avoid temporary List allocation with HTTP/3 trailers + +[PR #122677](https://github.com/dotnet/runtime/pull/122677) by @MihaZupan + +We can write directly into the final header collection, no need for the List in between. + +#### Refactor HTTP/3 server stream handling to consolidate exception handling for stream resets + +[PR #122561](https://github.com/dotnet/runtime/pull/122561) by @MihaZupan with GitHub Copilot + +> + +#### Reduce unsafe code usage in HttpHeaders + +[PR #122132](https://github.com/dotnet/runtime/pull/122132) by @GrabYourPitchforks + +The usage of GetArrayDataReference in HttpHeaders is unnecessary. Since the JIT can prove that accessing the 0th element of the array will not result in an IndexOutOfBoundsException (see the newarr two lines above the changed code), standard arra + +--- + +## Networking + +### New Features + +#### Add Uri.UriSchemeData constant + +[PR #123147](https://github.com/dotnet/runtime/pull/123147) by @stephentoub with GitHub Copilot + +Adds UriSchemeData constant to System.Uri for data: URIs, following the pattern established in .NET 6 for adding scheme constants. + +```csharp +namespace System +{ + public partial class Uri + { + /// Specifies that the URI is a data URI. + public static readonly string UriSchemeData = "data"; + } +} +``` + +#### Add null validation for relativeUri in Uri(Uri, Uri) constructor + +[PR #123134](https://github.com/dotnet/runtime/pull/123134) by @MihaZupan with GitHub Copilot + +The Uri(Uri, Uri) constructor threw NullReferenceException when passed a null relativeUri, instead of ArgumentNullException at parameter validation time. + +```csharp +// Before: throws NullReferenceException deep in CreateThisFromUri +// After: throws ArgumentNullException immediately +Uri baseUri = new Uri("http://localhost/"); +Uri result = new Uri(baseUri, (Uri)null); // ArgumentNullException with correct parameter name +``` + +#### Add support for .cgm (Computer Graphics Metafile) extension to MediaTypeMap + +[PR #122591](https://github.com/dotnet/runtime/pull/122591) by @stephentoub with GitHub Copilot + +> + +### Improvements + +#### Deny unmasked frame receive for WebSocket Server + +[PR #123485](https://github.com/dotnet/runtime/pull/123485) by @liveans + +Increasing RFC-compliance for WebSocket + +#### Fix another Uri debug assert + +[PR #123075](https://github.com/dotnet/runtime/pull/123075) by @MihaZupan + +Overlaps special-cases empty spans as not overlapping even if the pointer appears in the middle. + +#### Fix edge-case Uri debug assert failure + +[PR #123054](https://github.com/dotnet/runtime/pull/123054) by @MihaZupan + +If Compress removes the entire path, and that path was otherwise missing a leading slash, we can get into the case where dest.Length == start after the Compress call. + +#### Haiku: Mark unsupported advanced network functions + +[PR #121882](https://github.com/dotnet/runtime/pull/121882) by @trungnt2910 + +Add the UnsupportedOSPlatformAttribute for Haiku to managed network functions in System.Net.NetworkInformation to provide a consistent API on Haiku. + +--- + +## Other + +### New Features + +#### Add JsonSerializerDefaults.Strict support to JsonSourceGenerationOptionsAttribute constructor + +[PR #122899](https://github.com/dotnet/runtime/pull/122899) by @PranavSenthilnathan with GitHub Copilot + +> + +```csharp +> using System.Text.Json; +> using System.Text.Json.Serialization; +> +> internal static class Reproduction +> { +> public static void Main() +> { +> // Crash at runtime +> _ = typeof(SourceGenerationContext).GetCustomAttributes(true); +> } +> } +> +> [JsonSourceGenerationOptions(JsonSerializerDefaults.Strict)] +> [JsonSerializable(typeof(Example))] +> internal partial class SourceGenerationContext : JsonSerializerContext; +> +> internal class Example; +> +``` + +#### Fix Regex.Escape to not escape vertical tab and add comprehensive tests + +[PR #123088](https://github.com/dotnet/runtime/pull/123088) by @stephentoub with GitHub Copilot + +main PR https://github.com/dotnet/runtime/pull/120625 + +#### Add [OverloadResolutionPriority(1)] to MemoryMarshal.AsRef(Span) + +[PR #122330](https://github.com/dotnet/runtime/pull/122330) by @stephentoub with GitHub Copilot + +> + +```csharp +> ref T AsRef(Span span) +> ref readonly T AsRef(ReadOnlySpan span) +> +``` + +### Performance + +#### Fix IndexOfAnyInRange inconsistent behavior with invalid ranges across vectorized/scalar paths + +[PR #123365](https://github.com/dotnet/runtime/pull/123365) by @EgorBo with GitHub Copilot + +IndexOfAnyInRange and related APIs return inconsistent results for invalid ranges (where highInclusive < lowInclusive) depending on whether hardware intrinsics are enabled. The vectorized path computes highInclusive - lowInclusive, which wraps to a large positive value for unsigned types, causing incorrect matches. + +```csharp +ReadOnlySpan data = [50]; +int result = data.IndexOfAnyInRange((byte)200, (byte)100); +// Returns 0 with intrinsics enabled (incorrect) +// Returns -1 with intrinsics disabled (correct) +``` + +### Improvements + +#### Change TypeMapLazyDictionary to use direct cast instead of 'as' operator for RuntimeAssembly + +[PR #122885](https://github.com/dotnet/runtime/pull/122885) by @jtschuster with GitHub Copilot + +Replaced as RuntimeAssembly with direct cast (RuntimeAssembly?) in TypeMapLazyDictionary.CreateMaps() for both Assembly.Load() and Assembly.GetEntryAssembly() calls. + +--- + +## Hardware Intrinsics + +### New Features + +#### Sve2: Add ShiftRightLogicalNarrowingSaturate(Even|Odd) + +[PR #123888](https://github.com/dotnet/runtime/pull/123888) by @a74nh + +Sve2: Add ShiftRightLogicalNarrowingSaturate(Even|Odd) + +#### SVE: Add float/double args for mask APIs + +[PR #123947](https://github.com/dotnet/runtime/pull/123947) by @a74nh + +Everything except for the CreateWhile*() changes + +### Improvements + +#### Fix SVE2 API for Odd/Even methods + +[PR #122173](https://github.com/dotnet/runtime/pull/122173) by @ylpoonlg + +Fixes https://github.com/dotnet/runtime/issues/121961. + +#### Fix SVE2 API for RotateComplex methods + +[PR #122172](https://github.com/dotnet/runtime/pull/122172) by @ylpoonlg + +Rename argument names for the following methods: + +--- + +## File I/O + +### New Features + +#### Add OpenStandardInputHandle, OpenStandardOutputHandle, and OpenStandardErrorHandle APIs + +[PR #123478](https://github.com/dotnet/runtime/pull/123478) by @adamsitnik with GitHub Copilot + +✨ Let Copilot coding agent [set things up for you](https://github.com/dotnet/runtime/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%2 + +#### Add File.OpenNullHandle() for efficient process I/O redirection + +[PR #123483](https://github.com/dotnet/runtime/pull/123483) by @adamsitnik with GitHub Copilot + +Adds File.OpenNullHandle() API to obtain a handle to the system's null device (NUL on Windows, /dev/null on Unix). This enables efficient discarding of process output/error streams or providing empty input without the overhead of reading and ignoring data. + +```csharp +process.StartInfo.RedirectStandardOutput = true; +process.OutputDataReceived += (sender, e) => { }; // Wasteful +process.BeginOutputReadLine(); +``` + +#### Add CancellationToken overloads for TextWriter.WriteAsync and WriteLineAsync + +[PR #122127](https://github.com/dotnet/runtime/pull/122127) by @stephentoub with GitHub Copilot + +Successfully implemented the approved API proposal for adding CancellationToken overloads to TextWriter. The implementation: + +```csharp +> namespace System.IO; +> +> public abstract class TextWriter +> { +> public Task WriteAsync(string? value, CancellationToken token); +> public Task WriteLineAsync(CancellationToken token); +> public Task WriteLineAsync(string? value, CancellationToken token); +> } +> +``` + +### Performance + +#### Optimize Directory.GetFiles by passing safe patterns to NtQueryDirectoryFile + +[PR #122947](https://github.com/dotnet/runtime/pull/122947) by @jozkee with GitHub Copilot + +On Windows, Directory.GetFiles with search patterns is O(N) instead of O(log N) because .NET Core+ always passes null to NtQueryDirectoryFile's FileName parameter, enumerating all files and filtering in managed code. + +--- + +## Cryptography & Security + +### New Features + +#### Add AppContext switch for SignedInfo maximum number of references. + +[PR #123721](https://github.com/dotnet/runtime/pull/123721) by @vcsjones + +By default, the SignedInfo class will process at most 100 references per SignedInfo as a security mitigation. In .NET Framework, this value is configurable by registry. In .NET Core however, this value is hardcoded to 100. For users that are currentl + +#### Remove managed implementation from SP800-108 on Windows + +[PR #122816](https://github.com/dotnet/runtime/pull/122816) by @vcsjones + +It was only used for Windows 7. + +### Improvements + +#### Fix FromBase64Transform buffer sizing and output buffer handling + +[PR #122805](https://github.com/dotnet/runtime/pull/122805) by @stephentoub with GitHub Copilot + +> + +```csharp +// Before: rents only for new input, ignoring retained bytes +transformBuffer = transformBufferArray = CryptoPool.Rent(inputCount); + +// After: rents for total bytes (retained + new input) +transformBuffer = transformBufferArray = CryptoPool.Rent(bytesToTransform); +``` + +--- + +## Runtime + +### New Features + +#### Add side-effect free debugger display to `ValueStringBuilder`. + +[PR #122265](https://github.com/dotnet/runtime/pull/122265) by @teo-tsirpanis + +Calling ToString() clears the builder, which can cause surprises when debugging. + +#### Add fast path to Array.ConstrainedCopy for single-dimensional arrays + +[PR #122530](https://github.com/dotnet/runtime/pull/122530) by @jkotas with GitHub Copilot + +> + +### Performance + +#### Fix vectorization of `Ascii.Equals` for lengths 8..15 + +[PR #123115](https://github.com/dotnet/runtime/pull/123115) by @pentp + +In case of WideningLoader it currently uses Vector128.Count (16) as the minimum length, but 8 bytes/chars is the actual minimum. + +--- + +## Memory + +### Improvements + +#### Fix Base64.DecodeFromUtf8 consuming whitespace in partial final quantum when isFinalBlock=false + +[PR #123313](https://github.com/dotnet/runtime/pull/123313) by @MihaZupan with GitHub Copilot + +Base64.DecodeFromUtf8() incorrectly consumed whitespace characters when a final quantum (containing padding =) was split by whitespace and isFinalBlock=false. This broke streaming decoders that retry with isFinalBlock=true after receiving more data. + +```csharp +// Before: bytesConsumed=2, making recovery impossible +Base64.DecodeFromUtf8("AQ\r\nQ="u8, output, out int consumed, out _, isFinalBlock: false); +// consumed=2, but "Q=" slice is invalid + +// After: bytesConsumed=0, allowing retry with full input +Base64.DecodeFromUtf8("AQ\r\nQ="u8, output, out int consumed, out _, isFinalBlock: false); +Base64.DecodeFromUtf8("AQ\r\nQ="u8, output, out _, out _, isFinalBlock: true); // succeeds +``` + +#### Use existing Base64 helpers for Base64FormattingOptions.InsertLineBreaks + +[PR #123403](https://github.com/dotnet/runtime/pull/123403) by @MihaZupan + +Use existing Base64 helpers for Base64FormattingOptions.InsertLineBreaks + +#### Fix Base64 decoding edge cases with small destinations and whitespace + +[PR #123260](https://github.com/dotnet/runtime/pull/123260) by @MihaZupan + +From InvalidDataFallback we'll call back into DecodeFrom to try and process more data. + +--- + +## Regular Expressions + +### Improvements + +#### Port backreference SequenceEquals optimization to RegexCompiler + +[PR #123914](https://github.com/dotnet/runtime/pull/123914) by @stephentoub + +The regex source generator was using SequenceEqual when comparing case-sensitive backreferences, but the regex compiler wasn't. This just adds in that missing code, as well as some more tests for case-insensitive backreferences. + +#### Port alternation switch optimization from source generator to RegexCompiler + +[PR #122959](https://github.com/dotnet/runtime/pull/122959) by @stephentoub with GitHub Copilot + +Original prompt + +--- + +## JSON Serialization + +### New Features + +#### Add GetTypeInfo() and TryGetTypeInfo() to JsonSerializerOptions + +[PR #123940](https://github.com/dotnet/runtime/pull/123940) by @stephentoub with GitHub Copilot + +Implements the approved API from API review to add generic overloads of GetTypeInfo that return JsonTypeInfo directly, eliminating the need for manual downcasting. + +```csharp +namespace System.Text.Json; + +public partial class JsonSerializerOptions +{ + public JsonTypeInfo GetTypeInfo(); + public bool TryGetTypeInfo([NotNullWhen(true)] out JsonTypeInfo? typeInfo); +} +``` + +### Improvements + +#### Fix JsonSerializer.Serialize producing invalid JSON for [JsonExtensionData] with JsonObject + +[PR #122838](https://github.com/dotnet/runtime/pull/122838) by @stephentoub with GitHub Copilot + +> + +```csharp +var mix = new Mix { Id = 1, Extra = new JsonObject { ["nested"] = true } }; +JsonSerializer.Serialize(mix); +// Before: {"Id":1,{"nested":true}} ← invalid JSON +// After: {"Id":1,"nested":true} ← correct +``` + +--- + +## Compression + +### New Features + +#### Add ZipArchiveEntry.Open(FileAccess) and OpenAsync(FileAccess, CancellationToken) overloads to ZipArchiveEntry + +[PR #122032](https://github.com/dotnet/runtime/pull/122032) by @iremyux + +This PR adds new overloads to ZipArchiveEntry.Open() and ZipArchiveEntry.OpenAsync() that accept a FileAccess parameter, allowing users to specify the desired access mode when opening an entry stream. + +### Improvements + +#### Fix reachable Debug.Assert in InterleavedZipPackagePartStream.Length + +[PR #123817](https://github.com/dotnet/runtime/pull/123817) by @stephentoub with GitHub Copilot + +Original prompt + +```csharp +> [Fact] +> public void InterleavedZipPackagePartStream_Length_Assert() +> { +> using MemoryStream package = new(_partPieceSampleZipPackage); +> +> using Package zipPackage = Package.Open(package, FileMode.Open, FileAccess.Read); +> PackagePart partEntry = zipPackage.GetPart(new Uri("/ReadablePartPieceEntry.bin", UriKind.Relative)); +> using Stream stream = partEntry.GetStream(FileMode.Open); +> Assert.NotEqual(0, stream.Length); +> } +> +``` + +--- + +## Globalization + +### New Features + +#### Add IdnMapping Span-based APIs (TryGetAscii/TryGetUnicode) + +[PR #123593](https://github.com/dotnet/runtime/pull/123593) by @stephentoub with GitHub Copilot + +Adds span-based APIs to IdnMapping for zero-allocation IDN encoding/decoding: + +```csharp +namespace System.Globalization +{ + public sealed class IdnMapping + { + public bool TryGetAscii(ReadOnlySpan unicode, Span destination, out int charsWritten); + public bool TryGetUnicode(ReadOnlySpan ascii, Span destination, out int charsWritten); + } +} +``` + +### Improvements + +#### Support ICU v78 changes including IDN and Japanese Meiji era start date + +[PR #122480](https://github.com/dotnet/runtime/pull/122480) by @tarekgh + +ICU has released version 78, which includes changes to IDN handling that caused some of our tests to fail when using the updated library. + +--- + +## System.Runtime.InteropServices.JavaScript + +### New Features + +#### [browser][coreCLR] HTTP and WS client implementation in JS + +[PR #123400](https://github.com/dotnet/runtime/pull/123400) by @pavelsavara + +Fixes https://github.com/dotnet/runtime/issues/120216 + +#### [browser][coreCLR] implement JS interop + +[PR #123131](https://github.com/dotnet/runtime/pull/123131) by @pavelsavara + +Fixes https://github.com/dotnet/runtime/issues/120703 + +--- + +## Buffers + +### New Features + +#### Add Base64 parity APIs with Base64Url + +[PR #123151](https://github.com/dotnet/runtime/pull/123151) by @stephentoub with GitHub Copilot + +No security vulnerabilities were detected. + +### Improvements + +#### Fix Base64{Url} incorrectly handling small destinations when inputs contain whitespace + +[PR #123223](https://github.com/dotnet/runtime/pull/123223) by @stephentoub with GitHub Copilot + +Base64{Url}.DecodeFromUtf8 and DecodeFromChars incorrectly return DestinationTooSmall when input contains whitespace and destination is small but sufficient for actual data. + +```csharp +byte[] input = Encoding.UTF8.GetBytes(" zA== "); +Base64Url.DecodeFromUtf8(input, new byte[5]); // ✓ writes 1 byte +Base64Url.DecodeFromUtf8(input, new byte[1]); // ✗ was: "Destination is too short" + +Base64Url.DecodeFromChars(new string(' ', 8), new byte[1]); // ✗ was: "Destination is too short" +``` + +--- + +## LINQ + +### New Features + +#### Add coalescence optimization for AsyncEnumerable Append/Prepend/Concat operations + +[PR #122389](https://github.com/dotnet/runtime/pull/122389) by @stephentoub with GitHub Copilot + +In .NET 10 AsyncEnumerable LINQ features are now included into BCL instead of the standalone package System.Linq.Async. Most things work as expected, but in the scenario of Append followed by a SumAsync we are seeing a regression in performance that is not expected (one of the scenarios we have noted down so far in our internal testing). + +```csharp +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Running; + +BenchmarkRunner.Run(BenchmarkConverter.TypeToBenchmarks(typeof(AppendTest))); + +[MemoryDiagnoser] +[MinColumn, MaxColumn, Q1Column, Q3Column, AllStatisticsColumn] +[JsonExporterAttribute.Full] +public class AppendTest +{ + [Benchmark] + public async Task AppendInts() + { + var enumerable = AsyncEnumerable.Empty(); + for (int i = 0; i < 10000; i++) + enumerable = enumerable.Append(i); + + return await enumerable.SumAsync(); + } +} +``` + +#### Add early return in TryGetLast for empty results. + +[PR #123306](https://github.com/dotnet/runtime/pull/123306) by @prozolic + +This PR adds a fast path in IEnumerableSkipTakeIterator.TryGetLast. When source is an Iterator and GetCount(onlyIfCheap: true) returns a valid count (not -1), check if count <= _minIndexInclusive. In this case, immediately return with found=false. + +--- + +## Collections + +### New Features + +#### Add cancellation token check to BlockingCollection.TakeFromAny fast path + +[PR #122410](https://github.com/dotnet/runtime/pull/122410) by @stephentoub with GitHub Copilot + +BlockingCollecction.TakeFromAny do not check state of cancellationToken (3rd argument). + +```csharp +var bc1 = new BlockingCollection(); +var bc2 = new BlockingCollection(); +bc1.Add(1); +bc2.Add(2); + +var cts = new CancellationTokenSource(); +cts.Cancel(); + +// Previously: would successfully take item 1 or 2 +// Now: throws OperationCanceledException immediately +BlockingCollection.TakeFromAny(new[] { bc1, bc2 }, out int item, cts.Token); +``` + +### Performance + +#### Optimize HashSet.UnionWith to copy data from another HashSet when empty + +[PR #122952](https://github.com/dotnet/runtime/pull/122952) by @stephentoub with GitHub Copilot + +When UnionWith is called on an empty HashSet with another HashSet that has the same effective comparer, we can use ConstructFrom to copy the internal data structures directly instead of adding each element individually with collision ch + +```csharp +// Before: iterates through all elements, computing hash and checking collisions for each +// After: copies internal arrays directly when destination is empty and comparers match +if (Count == 0 && other is HashSet otherAsSet && EffectiveEqualityComparersAreEqual(this, otherAsSet)) +{ + ConstructFrom(otherAsSet); + return; +} +``` + +--- + +## System.Formats.Tar + +### New Features + +#### Add tar tests for >8GB file entries using simulated streams + +[PR #123091](https://github.com/dotnet/runtime/pull/123091) by @rzikm with GitHub Copilot + +Adds automated tests for tar archives with >8GB file entries using SimulatedDataStream and ConnectedStreams to avoid materializing large data. Previous manual tests required actual disk space and were unsuitable for CI. + +#### Add regression tests for TarReader.GetNextEntry after DataStream disposal + +[PR #122945](https://github.com/dotnet/runtime/pull/122945) by @stephentoub with GitHub Copilot + +> + +```csharp +> using (var tarReader = new TarReader(unseekableStream)) +> { +> TarEntry? entry; +> while ((entry = tarReader.GetNextEntry()) != null) +> { +> Stream s = entry.DataStream; +> s.CopyTo(someOtherStream); +> s.Dispose(); +> } +> } +> +``` + +--- + +## Numerics + +### New Features + +#### Add SSE implementation to Matrix4x4.GetDeterminant + +[PR #123954](https://github.com/dotnet/runtime/pull/123954) by @alexcovington + +This PR adds an SSE implementation for Matrix4x4.GetDeterminant. Performance improves by about 15% by vectorizing the operations. + +--- + +## Tensor Primitives + +### Performance + +#### Vectorize BitIncrement and BitDecrement for float/double in TensorPrimitives + +[PR #123610](https://github.com/dotnet/runtime/pull/123610) by @stephentoub with GitHub Copilot + +Implements SIMD vectorization for BitIncrement and BitDecrement operations on float and double types in TensorPrimitives. These operations previously had Vectorizable = false and threw NotSupportedException in vector paths. + +--- + +## Microsoft.Extensions.Logging + +### Improvements + +#### FormattedLogValues - Small optimization for index operator + +[PR #122059](https://github.com/dotnet/runtime/pull/122059) by @snakefoot + +Resolves #122046 (Removed "expensive" Count-check, since also exists in LogValuesFormatter) + +--- + +## System.Diagnostics + +### Improvements + +#### [browser][CoreCLR] Trimming feature System.Diagnostics.StackTrace.IsLineNumberSupported + +[PR #123429](https://github.com/dotnet/runtime/pull/123429) by @pavelsavara + +saves 214KB of uncompressed IL from hello world + +--- + +## System.Runtime.InteropServices + +### New Features + +#### Add AddRef to callee that caches interface ptr + +[PR #122509](https://github.com/dotnet/runtime/pull/122509) by @jtschuster + +Callee was missing an AddRef when returning the cached interface pointer. Tests no longer fail on Linux with this change locally. + +--- + +## System.Runtime.CompilerServices + +### New Features + +#### Adding support for aligning AllocateTypeAssociatedMemory + +[PR #122094](https://github.com/dotnet/runtime/pull/122094) by @tannergooding + +Adding support for aligning AllocateTypeAssociatedMemory + +--- + + +## Threading & Time + +### Performance + +#### Major TimeZone performance improvement with per-year caching + +[PR #119662](https://github.com/dotnet/runtime/pull/119662) by @tarekgh + +A significant rewrite of time zone handling introduces a **per-year cache** for time zone transitions, dramatically improving performance for time conversions. The cache stores all transitions for a given year in UTC format, eliminating repeated rule lookups during conversions. + +**Performance improvements (Windows):** +| Operation | Speedup | +|-----------|--------| +| ConvertTimeFromUtc | **3.9x faster** | +| ConvertTime (Local DateKind) | **3.5x faster** | +| ConvertTimeToUtc | **3.0x faster** | +| DateTime.Now | **2.8x faster** | +| GetUtcOffset | **2.5x faster** | + +**Performance improvements (Linux):** +| Operation | Speedup | +|-----------|--------| +| ConvertTimeToUtc | **4.7x faster** | +| ConvertTime (Local DateKind) | **4.3x faster** | +| ConvertTimeFromUtc | **3.5x faster** | +| DateTime.Now | **3.5x faster** | +| GetUtcOffset | **2.9x faster** | + +This change also fixes several correctness issues with time zone handling that were difficult to address in the previous implementation. + + +#### Use QueryUnbiasedInterruptTime for more responsive Windows timer behavior + +[PR #122706](https://github.com/dotnet/runtime/pull/122706) by @tannergooding + +Windows apps can now achieve higher timer responsiveness (sub-millisecond) when they opt-in to higher precision tick times. Previously, Windows was restricted to 10-16ms (typically 15.5ms) responsiveness and did not respect apps which set higher precision tick times, while Unix systems already used more responsive timers like `CLOCK_MONOTONIC_COARSE` and `CLOCK_UPTIME_RAW`. + +This change switches from `GetTickCount64` to `QueryUnbiasedInterruptTime` on Windows, aligning behavior with Unix systems and the OS's own Wait APIs which no longer include sleep/hibernate time in timeout checks. + +**Note:** This is a breaking change - timeouts now exclude time spent in sleep/hibernate states on Windows, matching Unix behavior. + +#### Lazy-initialize DateTimeFormatInfoScanner.m_dateWords + +[PR #123886](https://github.com/dotnet/runtime/pull/123886) by @stephentoub + +Reduces memory allocation for cultures that don't have date words by lazy-initializing the scanner's date words collection. Only a subset of cultures have date words, so this avoids unnecessary allocations for the majority of cases. + +### Improvements + +#### Fix timeout/duration calculations using monotonic time and precise tick accumulation + +[PR #123980](https://github.com/dotnet/runtime/pull/123980) by @MihaZupan with GitHub Copilot + +Fixed socket timeout calculations that incorrectly used `.Milliseconds` (returns component 0-999) instead of `.TotalMilliseconds`. For a 2.5 second duration, `.Milliseconds` returns `500` while `.TotalMilliseconds` returns `2500.0`. Also switched to monotonic time source to avoid issues with system clock adjustments. + +--- + + +## Threading (Additional) + +### New Features + +#### Add generic And and Or methods to System.Threading.Interlocked + +[PR #120978](https://github.com/dotnet/runtime/pull/120978) by @EgorBo with GitHub Copilot + +Adds generic `Interlocked.And` and `Interlocked.Or` methods that work with any enum type or integer type, complementing the existing non-generic overloads. + +--- + +## JSON Serialization (Additional) + +### New Features + +#### Support IReadOnlyDictionary as JsonExtensionData + +[PR #120636](https://github.com/dotnet/runtime/pull/120636) by @stephentoub with GitHub Copilot + +`[JsonExtensionData]` now supports `IReadOnlyDictionary` in addition to the previously supported mutable dictionary types. + +--- + +## Regular Expressions (Additional) + +### Performance + +#### Optimize regex patterns with both beginning and end anchors for early fail-fast + +[PR #120916](https://github.com/dotnet/runtime/pull/120916) by @stephentoub with GitHub Copilot + +Regex patterns that have both beginning (`^`) and end (`$`) anchors can now fail-fast earlier when the input length doesn't match the expected pattern length. + +--- + +## Reflection.Emit + +### New Features + +#### Support function pointer types in System.Reflection.Emit + +[PR #119935](https://github.com/dotnet/runtime/pull/119935) by @jgh07 + +Adds support for creating and working with function pointer types in the Reflection.Emit API. + +#### Support references to unmanaged function pointers in Reflection.Emit + +[PR #121128](https://github.com/dotnet/runtime/pull/121128) by @jgh07 + +Extends Reflection.Emit to support references to unmanaged function pointers, enabling more advanced interop scenarios. + +--- + +## Networking (Security) - Additional + +### New Features + +#### Add missing TlsAlertMessage members + +[PR #120260](https://github.com/dotnet/runtime/pull/120260) by @rzikm + +Adds missing TLS alert message constants to the `TlsAlertMessage` enum for more complete TLS error handling. + +--- + + +## Compression (Additional) + +### New Features + +#### Implement ZStandard Stream, Encoder, Decoder + +[PR #119575](https://github.com/dotnet/runtime/pull/119575) by @rzikm + +Full implementation of `ZStandardStream` with encoder and decoder support. This complements the `DecompressionMethods.Zstandard` HTTP support with direct streaming APIs for Zstandard compression/decompression. + +#### Add ZipArchiveEntry.Open(FileAccess) overloads + +[PR #122032](https://github.com/dotnet/runtime/pull/122032) by @iremyux + +New overloads `Open(FileAccess)` and `OpenAsync(FileAccess, CancellationToken)` allow specifying read-only access when opening ZIP entries in Update mode. Previously, opening any entry in Update mode would decompress the entire entry into memory even when only reading was needed. + +```csharp +// Before: Always loads entire entry into memory in Update mode +using var stream = entry.Open(); + +// After: Can open read-only without loading into memory +using var stream = entry.Open(FileAccess.Read); +``` + +#### Make ZipArchiveEntry.CompressionMethod public + +[PR #122045](https://github.com/dotnet/runtime/pull/122045) by @iremyux + +Exposes the compression method of ZIP archive entries through a new public `ZipCompressionMethod` enum and `CompressionMethod` property on `ZipArchiveEntry`. + +--- -- [What's new in .NET 11](https://learn.microsoft.com/dotnet/core/whats-new/dotnet-11/overview) documentation From 1aa494c98076fbacc42d222bbf7c1d04d6dd480d Mon Sep 17 00:00:00 2001 From: Art Leonard Date: Thu, 5 Feb 2026 14:53:02 -0800 Subject: [PATCH 03/11] Revise release notes for .NET 11 Libraries Preview 1 Updated release notes for .NET 11 Libraries Preview 1 to enhance clarity and detail regarding new features, performance improvements, and notable changes. --- .../11.0/preview/preview1/libraries.md | 79 ++++++++++++------- 1 file changed, 50 insertions(+), 29 deletions(-) diff --git a/release-notes/11.0/preview/preview1/libraries.md b/release-notes/11.0/preview/preview1/libraries.md index 5f327d286f..108bd3f268 100644 --- a/release-notes/11.0/preview/preview1/libraries.md +++ b/release-notes/11.0/preview/preview1/libraries.md @@ -1,8 +1,15 @@ -# What's New in .NET 11 Libraries (Preview 1) +# What's New in .NET 11 Libraries - Release Notes -This summarizes new features, performance improvements, and notable changes in .NET Libraries in .NET 11 Preview 1. +This document summarizes new features, performance improvements, and notable changes coming to .NET Libraries in .NET 11. -## Feature Areas + +## Highlights + +- **43** new features and APIs +- **9** performance improvements +- **74** total notable changes across **27** areas + +## Table of Contents - [Threading & Time](#threading--time) (3) - [Networking (HTTP)](#networking-http) (7) @@ -180,7 +187,7 @@ Add the UnsupportedOSPlatformAttribute for Haiku to managed network functions in ```csharp > using System.Text.Json; > using System.Text.Json.Serialization; -> +> > internal static class Reproduction > { > public static void Main() @@ -189,11 +196,11 @@ Add the UnsupportedOSPlatformAttribute for Haiku to managed network functions in > _ = typeof(SourceGenerationContext).GetCustomAttributes(true); > } > } -> +> > [JsonSourceGenerationOptions(JsonSerializerDefaults.Strict)] > [JsonSerializable(typeof(Example))] > internal partial class SourceGenerationContext : JsonSerializerContext; -> +> > internal class Example; > ``` @@ -303,7 +310,7 @@ Successfully implemented the approved API proposal for adding CancellationToken ```csharp > namespace System.IO; -> +> > public abstract class TextWriter > { > public Task WriteAsync(string? value, CancellationToken token); @@ -495,7 +502,7 @@ This PR adds new overloads to ZipArchiveEntry.Open() and ZipArchiveEntry.OpenAsy > public void InterleavedZipPackagePartStream_Length_Assert() > { > using MemoryStream package = new(_partPieceSampleZipPackage); -> +> > using Package zipPackage = Package.Open(package, FileMode.Open, FileAccess.Read); > PackagePart partEntry = zipPackage.GetPart(new Uri("/ReadablePartPieceEntry.bin", UriKind.Relative)); > using Stream stream = partEntry.GetStream(FileMode.Open); @@ -781,27 +788,41 @@ Adding support for aligning AllocateTypeAssociatedMemory [PR #119662](https://github.com/dotnet/runtime/pull/119662) by @tarekgh -A significant rewrite of time zone handling introduces a **per-year cache** for time zone transitions, dramatically improving performance for time conversions. The cache stores all transitions for a given year in UTC format, eliminating repeated rule lookups during conversions. - -**Performance improvements (Windows):** -| Operation | Speedup | -|-----------|--------| -| ConvertTimeFromUtc | **3.9x faster** | -| ConvertTime (Local DateKind) | **3.5x faster** | -| ConvertTimeToUtc | **3.0x faster** | -| DateTime.Now | **2.8x faster** | -| GetUtcOffset | **2.5x faster** | - -**Performance improvements (Linux):** -| Operation | Speedup | -|-----------|--------| -| ConvertTimeToUtc | **4.7x faster** | -| ConvertTime (Local DateKind) | **4.3x faster** | -| ConvertTimeFromUtc | **3.5x faster** | -| DateTime.Now | **3.5x faster** | -| GetUtcOffset | **2.9x faster** | - -This change also fixes several correctness issues with time zone handling that were difficult to address in the previous implementation. +A significant rewrite of time zone handling introduces a **per-year cache** for time zone transitions, improving performance for time conversions. The cache stores all transitions for a given year in UTC format, eliminating repeated rule lookups during conversions. + +**Windows Benchmarks:** +``` +BenchmarkDotNet v0.15.2, Windows 11 (10.0.26100.6584/24H2/2024Update/HudsonValley) +11th Gen Intel Core i7-11700 2.50GHz, 1 CPU, 16 logical and 8 physical cores +``` + +| Method | base/diff | Base Median (ns) | Diff Median (ns) | +|---------------------------------------|----------:|-----------------:|-----------------:| +| ConvertTimeFromUtc | 3.93 | 47.97 | 12.21 | +| ConvertTimeUsingLocalDateKind | 3.47 | 66.70 | 19.21 | +| ConvertTimeUsingUnspecifiedDateKind | 3.34 | 63.77 | 19.07 | +| ConvertTimeToUtc | 2.98 | 48.33 | 16.23 | +| DateTimeNow | 2.81 | 54.57 | 19.42 | +| GetUtcOffset | 2.48 | 98.64 | 39.83 | +| ConvertTimeUsingUtcDateKind | 2.39 | 19.66 | 8.23 | + +**Linux Benchmarks (WSL):** +``` +BenchmarkDotNet v0.15.2, Linux Ubuntu 25.04 (Plucky Puffin) +11th Gen Intel Core i7-11700 2.50GHz, 1 CPU, 16 logical and 8 physical cores +``` + +| Method | base/diff | Base Median (ns) | Diff Median (ns) | +|---------------------------------------|----------:|-----------------:|-----------------:| +| ConvertTimeToUtc | 4.70 | 63.80 | 13.57 | +| ConvertTimeUsingLocalDateKind | 4.25 | 80.09 | 18.84 | +| ConvertTimeUsingUnspecifiedDateKind | 4.01 | 79.23 | 19.78 | +| ConvertTimeFromUtc | 3.54 | 39.34 | 11.12 | +| DateTimeNow | 3.51 | 50.99 | 14.54 | +| GetUtcOffset | 2.87 | 100.40 | 34.94 | +| ConvertTimeUsingUtcDateKind | 1.64 | 17.60 | 10.73 | + +This change also fixes several correctness issues with time zone handling (fixes #24839, #24277, #25075, #118915, #114476). #### Use QueryUnbiasedInterruptTime for more responsive Windows timer behavior From 6ab0b6d499d2479d5ee09401a629cea6bc23c432 Mon Sep 17 00:00:00 2001 From: Art Leonard Date: Thu, 5 Feb 2026 14:54:03 -0800 Subject: [PATCH 04/11] Update title for .NET 11 Libraries release notes --- release-notes/11.0/preview/preview1/libraries.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release-notes/11.0/preview/preview1/libraries.md b/release-notes/11.0/preview/preview1/libraries.md index 108bd3f268..0dfdb60abb 100644 --- a/release-notes/11.0/preview/preview1/libraries.md +++ b/release-notes/11.0/preview/preview1/libraries.md @@ -1,4 +1,4 @@ -# What's New in .NET 11 Libraries - Release Notes +# .NET Libraries in .NET 11 Preview 1 - Release Notes This document summarizes new features, performance improvements, and notable changes coming to .NET Libraries in .NET 11. From b3aaa8bec790034cff47abfb0ad66e1b7927a9c2 Mon Sep 17 00:00:00 2001 From: Art Leonard Date: Thu, 5 Feb 2026 14:54:37 -0800 Subject: [PATCH 05/11] Revise introduction for clarity in libraries.md --- release-notes/11.0/preview/preview1/libraries.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release-notes/11.0/preview/preview1/libraries.md b/release-notes/11.0/preview/preview1/libraries.md index 0dfdb60abb..848c045142 100644 --- a/release-notes/11.0/preview/preview1/libraries.md +++ b/release-notes/11.0/preview/preview1/libraries.md @@ -1,6 +1,6 @@ # .NET Libraries in .NET 11 Preview 1 - Release Notes -This document summarizes new features, performance improvements, and notable changes coming to .NET Libraries in .NET 11. +Preview 1 includes new .NET Libraries features, performance improvements, and notable changes coming to .NET 11. ## Highlights From d445ebcbca26a046f623cfdf2c2bdf1211260bd8 Mon Sep 17 00:00:00 2001 From: Art Leonard Date: Thu, 5 Feb 2026 14:56:20 -0800 Subject: [PATCH 06/11] Fix formatting in libraries.md for LoopbackServer --- release-notes/11.0/preview/preview1/libraries.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release-notes/11.0/preview/preview1/libraries.md b/release-notes/11.0/preview/preview1/libraries.md index 848c045142..c84e4de5c0 100644 --- a/release-notes/11.0/preview/preview1/libraries.md +++ b/release-notes/11.0/preview/preview1/libraries.md @@ -84,7 +84,7 @@ var response = await client.GetStringAsync("http://ifconfig.me/ip"); [PR #123327](https://github.com/dotnet/runtime/pull/123327) by @pavelsavara -[browser] LoopbackServer - make GenericLoopbackServer.CloseWebSocket async +LoopbackServer - make GenericLoopbackServer.CloseWebSocket async #### Avoid temporary List allocation with HTTP/3 trailers From 6df7c0d613779c13bef22b6eb3e204a6fdcd4af1 Mon Sep 17 00:00:00 2001 From: Art Leonard Date: Thu, 5 Feb 2026 15:17:14 -0800 Subject: [PATCH 07/11] Revise libraries.md for .NET 11 Preview 1 updates (v2) Update release notes for .NET 11 Preview 1 with new features, improvements, and notable changes across various libraries. --- .../11.0/preview/preview1/libraries.md | 1023 +++-------------- 1 file changed, 172 insertions(+), 851 deletions(-) diff --git a/release-notes/11.0/preview/preview1/libraries.md b/release-notes/11.0/preview/preview1/libraries.md index c84e4de5c0..dd0a2ed850 100644 --- a/release-notes/11.0/preview/preview1/libraries.md +++ b/release-notes/11.0/preview/preview1/libraries.md @@ -1,527 +1,152 @@ # .NET Libraries in .NET 11 Preview 1 - Release Notes -Preview 1 includes new .NET Libraries features, performance improvements, and notable changes coming to .NET 11. - - -## Highlights - -- **43** new features and APIs -- **9** performance improvements -- **74** total notable changes across **27** areas - -## Table of Contents - -- [Threading & Time](#threading--time) (3) -- [Networking (HTTP)](#networking-http) (7) -- [Networking](#networking) (7) -- [Other](#other) (5) -- [Hardware Intrinsics](#hardware-intrinsics) (4) -- [File I/O](#file-i/o) (4) -- [Cryptography & Security](#cryptography-&-security) (3) -- [Runtime](#runtime) (3) -- [Memory](#memory) (3) -- [Regular Expressions](#regular-expressions) (2) -- [JSON Serialization](#json-serialization) (2) -- [Compression](#compression) (2) -- [Globalization](#globalization) (2) -- [System.Runtime.InteropServices.JavaScript](#systemruntimeinteropservicesjavascript) (2) -- [Buffers](#buffers) (2) -- [LINQ](#linq) (2) -- [Collections](#collections) (2) -- [System.Formats.Tar](#systemformatstar) (2) -- [Numerics](#numerics) (1) -- [Tensor Primitives](#tensor-primitives) (1) -- [Microsoft.Extensions.Logging](#microsoftextensionslogging) (1) -- [System.Diagnostics](#systemdiagnostics) (1) -- [System.Runtime.InteropServices](#systemruntimeinteropservices) (1) -- [System.Runtime.CompilerServices](#systemruntimecompilerservices) (1) - ---- - -## Networking (HTTP) - -### New Features - -#### Add DecompressionMethods.Zstandard for HTTP automatic decompression - -[PR #123531](https://github.com/dotnet/runtime/pull/123531) by @rzikm with GitHub Copilot - -Adds Zstandard compression support to DecompressionMethods for automatic HTTP response decompression, matching the API proposal. Follows the established pattern from Brotli support. - -```csharp -var handler = new HttpClientHandler -{ - AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Zstandard -}; - -using var client = new HttpClient(handler); -// Automatically decompresses zstd-encoded responses -var response = await client.GetAsync("https://example.com"); -``` - -#### Add an ASCII check for edge-case non-ASCII hosts that can't be Punycode encoded - -[PR #123934](https://github.com/dotnet/runtime/pull/123934) by @MihaZupan - -This is an edge-case where some hosts that exceed DNS limits (e.g. contain long labels) can't get Punycode encoded, and their IdnHost may return a non-ASCII value. - -#### Add support for socks5h proxy scheme - -[PR #123218](https://github.com/dotnet/runtime/pull/123218) by @MihaZupan with GitHub Copilot - -HttpClient now accepts socks5h:// proxy URIs. Previously, attempts to use this scheme threw NotSupportedException with message "Only the 'http', 'https', 'socks4', 'socks4a' and 'socks5' schemes are allowed for proxies." +.NET 11 Preview 1 includes new .NET Libraries features & enhancements: + +- [Zstandard Compression Support](#zstandard-compression-support) +- [ZipArchiveEntry.Open with FileAccess Parameter](#ziparchiveentry-open-with-fileaccess-parameter) +- [TimeZone Performance Improvements (per-year caching)](#timezone-performance-improvements) +- [Generic Interlocked.And and Interlocked.Or Methods](#generic-interlockedand-and-interlockedor-methods) +- [Span-based IDN APIs for IdnMapping](#span-based-idn-apis-for-idnmapping) +- [File.OpenNullHandle for Efficient I/O Redirection](#fileopennullhandle-for-efficient-io-redirection) +- [Standard Handle APIs for Console](#standard-handle-apis-for-console) +- [CancellationToken Overloads for TextWriter](#cancellationtoken-overloads-for-textwriter) +- [Function Pointer Support in Reflection.Emit](#function-pointer-support-in-reflectionemit) +- [SOCKS5h Proxy Support in HttpClient](#socks5h-proxy-support-in-httpclient) +- [HTTP Automatic Decompression with Zstandard](#http-automatic-decompression-with-zstandard) + +.NET Libraries updates in .NET 11: + +- [What's new in .NET 11](https://learn.microsoft.com/dotnet/core/whats-new/dotnet-11/overview) documentation + +## Zstandard Compression Support + +[dotnet/runtime #119575](https://github.com/dotnet/runtime/pull/119575) adds native Zstandard (zstd) compression support to .NET through the new `ZStandardStream` class, `ZStandardEncoder`, and `ZStandardDecoder`. + +Zstandard offers significantly faster compression and decompression compared to existing algorithms while maintaining competitive compression ratios. + +Benchmarks: + +| Method | Level | File | Algorithm | Mean | Size | Compressed | +|----------- |-------- |----------------- |---------- |------------:|-----:|-----:| +| Compress | Optimal | alice29.txt | Brotli | 2,306.40 μs | 148481 | 54517 | +| Compress | Optimal | alice29.txt | Zstandard | 842.743 μs | 148481 | 54919 | +| Compress | Optimal | alice29.txt | Deflate | 2,421.16 μs | 148481 | 53890 | +| | | | | | | | +| Decompress | Optimal | alice29.txt | Brotli | 320.82 μs | +| Decompress | Optimal | alice29.txt | Zstandard | 139.251 μs | +| Decompress | Optimal | alice29.txt | Deflate | 275.43 μs | +| | | | | | | | +| Compress | Fastest | TestDocument.pdf | Brotli | 300.40 μs | 121993 | 117104 | +| Compress | Fastest | TestDocument.pdf | Zstandard | 137.3 μs | 121993 | 119405 | +| Compress | Fastest | TestDocument.pdf | Deflate | 947.61 μs | 121993 | 121404 | +| | | | | | | | +| Decompress | Fastest | TestDocument.pdf | Brotli | 233.14 μs | +| Decompress | Fastest | TestDocument.pdf | Zstandard | 17.22 μs | +| Decompress | Fastest | TestDocument.pdf | Deflate | 238.81 μs | + +Usage: ```csharp -using var handler = new SocketsHttpHandler(); -handler.Proxy = new WebProxy("socks5h://username:password@proxy.example.com:1080"); -using HttpClient client = new HttpClient(handler); -var response = await client.GetStringAsync("http://ifconfig.me/ip"); -``` - -### Improvements - -#### [browser] LoopbackServer - make GenericLoopbackServer.CloseWebSocket async - -[PR #123327](https://github.com/dotnet/runtime/pull/123327) by @pavelsavara - -LoopbackServer - make GenericLoopbackServer.CloseWebSocket async - -#### Avoid temporary List allocation with HTTP/3 trailers - -[PR #122677](https://github.com/dotnet/runtime/pull/122677) by @MihaZupan - -We can write directly into the final header collection, no need for the List in between. - -#### Refactor HTTP/3 server stream handling to consolidate exception handling for stream resets - -[PR #122561](https://github.com/dotnet/runtime/pull/122561) by @MihaZupan with GitHub Copilot - -> - -#### Reduce unsafe code usage in HttpHeaders - -[PR #122132](https://github.com/dotnet/runtime/pull/122132) by @GrabYourPitchforks - -The usage of GetArrayDataReference in HttpHeaders is unnecessary. Since the JIT can prove that accessing the 0th element of the array will not result in an IndexOutOfBoundsException (see the newarr two lines above the changed code), standard arra - ---- - -## Networking - -### New Features - -#### Add Uri.UriSchemeData constant - -[PR #123147](https://github.com/dotnet/runtime/pull/123147) by @stephentoub with GitHub Copilot - -Adds UriSchemeData constant to System.Uri for data: URIs, following the pattern established in .NET 6 for adding scheme constants. - -```csharp -namespace System -{ - public partial class Uri - { - /// Specifies that the URI is a data URI. - public static readonly string UriSchemeData = "data"; - } -} -``` - -#### Add null validation for relativeUri in Uri(Uri, Uri) constructor - -[PR #123134](https://github.com/dotnet/runtime/pull/123134) by @MihaZupan with GitHub Copilot - -The Uri(Uri, Uri) constructor threw NullReferenceException when passed a null relativeUri, instead of ArgumentNullException at parameter validation time. - -```csharp -// Before: throws NullReferenceException deep in CreateThisFromUri -// After: throws ArgumentNullException immediately -Uri baseUri = new Uri("http://localhost/"); -Uri result = new Uri(baseUri, (Uri)null); // ArgumentNullException with correct parameter name -``` - -#### Add support for .cgm (Computer Graphics Metafile) extension to MediaTypeMap - -[PR #122591](https://github.com/dotnet/runtime/pull/122591) by @stephentoub with GitHub Copilot - -> - -### Improvements - -#### Deny unmasked frame receive for WebSocket Server - -[PR #123485](https://github.com/dotnet/runtime/pull/123485) by @liveans - -Increasing RFC-compliance for WebSocket - -#### Fix another Uri debug assert - -[PR #123075](https://github.com/dotnet/runtime/pull/123075) by @MihaZupan - -Overlaps special-cases empty spans as not overlapping even if the pointer appears in the middle. - -#### Fix edge-case Uri debug assert failure - -[PR #123054](https://github.com/dotnet/runtime/pull/123054) by @MihaZupan - -If Compress removes the entire path, and that path was otherwise missing a leading slash, we can get into the case where dest.Length == start after the Compress call. - -#### Haiku: Mark unsupported advanced network functions - -[PR #121882](https://github.com/dotnet/runtime/pull/121882) by @trungnt2910 - -Add the UnsupportedOSPlatformAttribute for Haiku to managed network functions in System.Net.NetworkInformation to provide a consistent API on Haiku. - ---- - -## Other - -### New Features - -#### Add JsonSerializerDefaults.Strict support to JsonSourceGenerationOptionsAttribute constructor - -[PR #122899](https://github.com/dotnet/runtime/pull/122899) by @PranavSenthilnathan with GitHub Copilot - -> - -```csharp -> using System.Text.Json; -> using System.Text.Json.Serialization; -> -> internal static class Reproduction -> { -> public static void Main() -> { -> // Crash at runtime -> _ = typeof(SourceGenerationContext).GetCustomAttributes(true); -> } -> } -> -> [JsonSourceGenerationOptions(JsonSerializerDefaults.Strict)] -> [JsonSerializable(typeof(Example))] -> internal partial class SourceGenerationContext : JsonSerializerContext; -> -> internal class Example; -> -``` - -#### Fix Regex.Escape to not escape vertical tab and add comprehensive tests - -[PR #123088](https://github.com/dotnet/runtime/pull/123088) by @stephentoub with GitHub Copilot - -main PR https://github.com/dotnet/runtime/pull/120625 - -#### Add [OverloadResolutionPriority(1)] to MemoryMarshal.AsRef(Span) - -[PR #122330](https://github.com/dotnet/runtime/pull/122330) by @stephentoub with GitHub Copilot +// Compress data +using var compressStream = new ZStandardStream(outputStream, CompressionMode.Compress); +await inputStream.CopyToAsync(compressStream); -> - -```csharp -> ref T AsRef(Span span) -> ref readonly T AsRef(ReadOnlySpan span) -> +// Decompress data +using var decompressStream = new ZStandardStream(inputStream, CompressionMode.Decompress); +await decompressStream.CopyToAsync(outputStream); ``` -### Performance +## ZipArchiveEntry.Open with FileAccess Parameter -#### Fix IndexOfAnyInRange inconsistent behavior with invalid ranges across vectorized/scalar paths +[dotnet/runtime #122032](https://github.com/dotnet/runtime/pull/122032) adds new overloads to `ZipArchiveEntry.Open()` that accept a `FileAccess` parameter, allowing users to specify the desired access mode when opening an entry stream. -[PR #123365](https://github.com/dotnet/runtime/pull/123365) by @EgorBo with GitHub Copilot +When a `ZipArchive` is opened in `ZipArchiveMode.Update`, calling `ZipArchiveEntry.Open()` always returns a read-write stream by invoking `OpenInUpdateMode()`. This causes the entire entry to be decompressed into memory, even when the caller only intends to read the entry's contents. -IndexOfAnyInRange and related APIs return inconsistent results for invalid ranges (where highInclusive < lowInclusive) depending on whether hardware intrinsics are enabled. The vectorized path computes highInclusive - lowInclusive, which wraps to a large positive value for unsigned types, causing incorrect matches. +New APIs: ```csharp -ReadOnlySpan data = [50]; -int result = data.IndexOfAnyInRange((byte)200, (byte)100); -// Returns 0 with intrinsics enabled (incorrect) -// Returns -1 with intrinsics disabled (correct) +public Stream Open(FileAccess access); +public Task OpenAsync(FileAccess access, CancellationToken cancellationToken = default); ``` -### Improvements - -#### Change TypeMapLazyDictionary to use direct cast instead of 'as' operator for RuntimeAssembly - -[PR #122885](https://github.com/dotnet/runtime/pull/122885) by @jtschuster with GitHub Copilot - -Replaced as RuntimeAssembly with direct cast (RuntimeAssembly?) in TypeMapLazyDictionary.CreateMaps() for both Assembly.Load() and Assembly.GetEntryAssembly() calls. - ---- - -## Hardware Intrinsics - -### New Features - -#### Sve2: Add ShiftRightLogicalNarrowingSaturate(Even|Odd) - -[PR #123888](https://github.com/dotnet/runtime/pull/123888) by @a74nh - -Sve2: Add ShiftRightLogicalNarrowingSaturate(Even|Odd) - -#### SVE: Add float/double args for mask APIs - -[PR #123947](https://github.com/dotnet/runtime/pull/123947) by @a74nh - -Everything except for the CreateWhile*() changes - -### Improvements - -#### Fix SVE2 API for Odd/Even methods - -[PR #122173](https://github.com/dotnet/runtime/pull/122173) by @ylpoonlg - -Fixes https://github.com/dotnet/runtime/issues/121961. - -#### Fix SVE2 API for RotateComplex methods - -[PR #122172](https://github.com/dotnet/runtime/pull/122172) by @ylpoonlg - -Rename argument names for the following methods: - ---- - -## File I/O - -### New Features +Update Mode Details: -#### Add OpenStandardInputHandle, OpenStandardOutputHandle, and OpenStandardErrorHandle APIs +- `FileAccess.Read`: Opens a read-only stream over the entry's compressed data without loading it into memory. Useful for streaming reads. +- `FileAccess.Write`: Opens an empty writable stream, discarding any existing entry data. Semantically equivalent to "replace the entry content entirely" (like `FileMode.Create`). +- `FileAccess.ReadWrite`: Same as parameterless `Open()`/`OpenAsync()` - loads existing data into memory and returns a read/write/seekable stream. -[PR #123478](https://github.com/dotnet/runtime/pull/123478) by @adamsitnik with GitHub Copilot +## TimeZone Performance Improvements -✨ Let Copilot coding agent [set things up for you](https://github.com/dotnet/runtime/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%2 +[dotnet/runtime #119662](https://github.com/dotnet/runtime/pull/119662) introduces a **per-year cache** for time zone transitions, dramatically improving performance for time conversions. The cache stores all transitions for a given year in UTC format, eliminating repeated rule lookups during conversions. -#### Add File.OpenNullHandle() for efficient process I/O redirection +### Windows -[PR #123483](https://github.com/dotnet/runtime/pull/123483) by @adamsitnik with GitHub Copilot - -Adds File.OpenNullHandle() API to obtain a handle to the system's null device (NUL on Windows, /dev/null on Unix). This enables efficient discarding of process output/error streams or providing empty input without the overhead of reading and ignoring data. - -```csharp -process.StartInfo.RedirectStandardOutput = true; -process.OutputDataReceived += (sender, e) => { }; // Wasteful -process.BeginOutputReadLine(); ``` - -#### Add CancellationToken overloads for TextWriter.WriteAsync and WriteLineAsync - -[PR #122127](https://github.com/dotnet/runtime/pull/122127) by @stephentoub with GitHub Copilot - -Successfully implemented the approved API proposal for adding CancellationToken overloads to TextWriter. The implementation: - -```csharp -> namespace System.IO; -> -> public abstract class TextWriter -> { -> public Task WriteAsync(string? value, CancellationToken token); -> public Task WriteLineAsync(CancellationToken token); -> public Task WriteLineAsync(string? value, CancellationToken token); -> } -> +BenchmarkDotNet v0.15.2, Windows 11 (10.0.26100.6584/24H2/2024Update/HudsonValley) +11th Gen Intel Core i7-11700 2.50GHz, 1 CPU, 16 logical and 8 physical cores ``` -### Performance - -#### Optimize Directory.GetFiles by passing safe patterns to NtQueryDirectoryFile - -[PR #122947](https://github.com/dotnet/runtime/pull/122947) by @jozkee with GitHub Copilot - -On Windows, Directory.GetFiles with search patterns is O(N) instead of O(log N) because .NET Core+ always passes null to NtQueryDirectoryFile's FileName parameter, enumerating all files and filtering in managed code. - ---- - -## Cryptography & Security - -### New Features - -#### Add AppContext switch for SignedInfo maximum number of references. - -[PR #123721](https://github.com/dotnet/runtime/pull/123721) by @vcsjones - -By default, the SignedInfo class will process at most 100 references per SignedInfo as a security mitigation. In .NET Framework, this value is configurable by registry. In .NET Core however, this value is hardcoded to 100. For users that are currentl - -#### Remove managed implementation from SP800-108 on Windows - -[PR #122816](https://github.com/dotnet/runtime/pull/122816) by @vcsjones - -It was only used for Windows 7. - -### Improvements - -#### Fix FromBase64Transform buffer sizing and output buffer handling +| Faster | base/diff | Base Median (ns) | Diff Median (ns) | +| ---------------------------------------------------- | ---------:| ----------------:| ----------------:| +| Baseline.Program.ConvertTimeFromUtc | 3.93 | 47.97 | 12.21 | +| Baseline.Program.ConvertTimeUsingLocalDateKind | 3.47 | 66.70 | 19.21 | +| Baseline.Program.ConvertTimeUsingUnspecifiedDateKind | 3.34 | 63.77 | 19.07 | +| Baseline.Program.ConvertTimeToUtc | 2.98 | 48.33 | 16.23 | +| Baseline.Program.DateTimeNow | 2.81 | 54.57 | 19.42 | +| Baseline.Program.GetUtcOffset | 2.48 | 98.64 | 39.83 | +| Baseline.Program.ConvertTimeUsingUtcDateKind | 2.39 | 19.66 | 8.23 | -[PR #122805](https://github.com/dotnet/runtime/pull/122805) by @stephentoub with GitHub Copilot +### Linux (WSL) -> - -```csharp -// Before: rents only for new input, ignoring retained bytes -transformBuffer = transformBufferArray = CryptoPool.Rent(inputCount); - -// After: rents for total bytes (retained + new input) -transformBuffer = transformBufferArray = CryptoPool.Rent(bytesToTransform); ``` - ---- - -## Runtime - -### New Features - -#### Add side-effect free debugger display to `ValueStringBuilder`. - -[PR #122265](https://github.com/dotnet/runtime/pull/122265) by @teo-tsirpanis - -Calling ToString() clears the builder, which can cause surprises when debugging. - -#### Add fast path to Array.ConstrainedCopy for single-dimensional arrays - -[PR #122530](https://github.com/dotnet/runtime/pull/122530) by @jkotas with GitHub Copilot - -> - -### Performance - -#### Fix vectorization of `Ascii.Equals` for lengths 8..15 - -[PR #123115](https://github.com/dotnet/runtime/pull/123115) by @pentp - -In case of WideningLoader it currently uses Vector128.Count (16) as the minimum length, but 8 bytes/chars is the actual minimum. - ---- - -## Memory - -### Improvements - -#### Fix Base64.DecodeFromUtf8 consuming whitespace in partial final quantum when isFinalBlock=false - -[PR #123313](https://github.com/dotnet/runtime/pull/123313) by @MihaZupan with GitHub Copilot - -Base64.DecodeFromUtf8() incorrectly consumed whitespace characters when a final quantum (containing padding =) was split by whitespace and isFinalBlock=false. This broke streaming decoders that retry with isFinalBlock=true after receiving more data. - -```csharp -// Before: bytesConsumed=2, making recovery impossible -Base64.DecodeFromUtf8("AQ\r\nQ="u8, output, out int consumed, out _, isFinalBlock: false); -// consumed=2, but "Q=" slice is invalid - -// After: bytesConsumed=0, allowing retry with full input -Base64.DecodeFromUtf8("AQ\r\nQ="u8, output, out int consumed, out _, isFinalBlock: false); -Base64.DecodeFromUtf8("AQ\r\nQ="u8, output, out _, out _, isFinalBlock: true); // succeeds +BenchmarkDotNet v0.15.2, Linux Ubuntu 25.04 (Plucky Puffin) +11th Gen Intel Core i7-11700 2.50GHz, 1 CPU, 16 logical and 8 physical cores ``` -#### Use existing Base64 helpers for Base64FormattingOptions.InsertLineBreaks - -[PR #123403](https://github.com/dotnet/runtime/pull/123403) by @MihaZupan - -Use existing Base64 helpers for Base64FormattingOptions.InsertLineBreaks - -#### Fix Base64 decoding edge cases with small destinations and whitespace - -[PR #123260](https://github.com/dotnet/runtime/pull/123260) by @MihaZupan - -From InvalidDataFallback we'll call back into DecodeFrom to try and process more data. - ---- - -## Regular Expressions - -### Improvements - -#### Port backreference SequenceEquals optimization to RegexCompiler +| Faster | base/diff | Base Median (ns) | Diff Median (ns) | +| ---------------------------------------------------- | ---------:| ----------------:| ----------------:| +| Baseline.Program.ConvertTimeToUtc | 4.70 | 63.80 | 13.57 | +| Baseline.Program.ConvertTimeUsingLocalDateKind | 4.25 | 80.09 | 18.84 | +| Baseline.Program.ConvertTimeUsingUnspecifiedDateKind | 4.01 | 79.23 | 19.78 | +| Baseline.Program.ConvertTimeFromUtc | 3.54 | 39.34 | 11.12 | +| Baseline.Program.DateTimeNow | 3.51 | 50.99 | 14.54 | +| Baseline.Program.GetUtcOffset | 2.87 | 100.40 | 34.94 | +| Baseline.Program.ConvertTimeUsingUtcDateKind | 1.64 | 17.60 | 10.73 | -[PR #123914](https://github.com/dotnet/runtime/pull/123914) by @stephentoub - -The regex source generator was using SequenceEqual when comparing case-sensitive backreferences, but the regex compiler wasn't. This just adds in that missing code, as well as some more tests for case-insensitive backreferences. - -#### Port alternation switch optimization from source generator to RegexCompiler - -[PR #122959](https://github.com/dotnet/runtime/pull/122959) by @stephentoub with GitHub Copilot - -Original prompt - ---- - -## JSON Serialization - -### New Features - -#### Add GetTypeInfo() and TryGetTypeInfo() to JsonSerializerOptions +This change also fixes several correctness issues with time zone handling (fixes #24839, #24277, #25075, #118915, #114476). -[PR #123940](https://github.com/dotnet/runtime/pull/123940) by @stephentoub with GitHub Copilot +## Generic Interlocked.And and Interlocked.Or Methods -Implements the approved API from API review to add generic overloads of GetTypeInfo that return JsonTypeInfo directly, eliminating the need for manual downcasting. +[dotnet/runtime #120978](https://github.com/dotnet/runtime/pull/120978) adds generic versions of the `And` and `Or` methods to `System.Threading.Interlocked`, enabling atomic bitwise operations on any enum type or integer type. ```csharp -namespace System.Text.Json; - -public partial class JsonSerializerOptions +public static class Interlocked { - public JsonTypeInfo GetTypeInfo(); - public bool TryGetTypeInfo([NotNullWhen(true)] out JsonTypeInfo? typeInfo); + public static T And(ref T location, T value) where T : struct; + public static T Or(ref T location, T value) where T : struct; } ``` -### Improvements - -#### Fix JsonSerializer.Serialize producing invalid JSON for [JsonExtensionData] with JsonObject +These methods support all integer primitive types (`byte`, `sbyte`, `short`, `ushort`, `int`, `uint`, `long`, `ulong`, `nint`, `nuint`) and any enum backed by these types. -[PR #122838](https://github.com/dotnet/runtime/pull/122838) by @stephentoub with GitHub Copilot - -> +Example usage: ```csharp -var mix = new Mix { Id = 1, Extra = new JsonObject { ["nested"] = true } }; -JsonSerializer.Serialize(mix); -// Before: {"Id":1,{"nested":true}} ← invalid JSON -// After: {"Id":1,"nested":true} ← correct -``` - ---- - -## Compression - -### New Features - -#### Add ZipArchiveEntry.Open(FileAccess) and OpenAsync(FileAccess, CancellationToken) overloads to ZipArchiveEntry +[Flags] +enum FilePermissions { None = 0, Read = 1, Write = 2, Execute = 4 } -[PR #122032](https://github.com/dotnet/runtime/pull/122032) by @iremyux +FilePermissions permissions = FilePermissions.Read; -This PR adds new overloads to ZipArchiveEntry.Open() and ZipArchiveEntry.OpenAsync() that accept a FileAccess parameter, allowing users to specify the desired access mode when opening an entry stream. +// Atomically add Write permission +Interlocked.Or(ref permissions, FilePermissions.Write); -### Improvements - -#### Fix reachable Debug.Assert in InterleavedZipPackagePartStream.Length - -[PR #123817](https://github.com/dotnet/runtime/pull/123817) by @stephentoub with GitHub Copilot - -Original prompt - -```csharp -> [Fact] -> public void InterleavedZipPackagePartStream_Length_Assert() -> { -> using MemoryStream package = new(_partPieceSampleZipPackage); -> -> using Package zipPackage = Package.Open(package, FileMode.Open, FileAccess.Read); -> PackagePart partEntry = zipPackage.GetPart(new Uri("/ReadablePartPieceEntry.bin", UriKind.Relative)); -> using Stream stream = partEntry.GetStream(FileMode.Open); -> Assert.NotEqual(0, stream.Length); -> } -> +// Atomically remove Execute permission +Interlocked.And(ref permissions, ~FilePermissions.Execute); ``` ---- - -## Globalization +## Span-based IDN APIs for IdnMapping -### New Features - -#### Add IdnMapping Span-based APIs (TryGetAscii/TryGetUnicode) - -[PR #123593](https://github.com/dotnet/runtime/pull/123593) by @stephentoub with GitHub Copilot - -Adds span-based APIs to IdnMapping for zero-allocation IDN encoding/decoding: +[dotnet/runtime #123593](https://github.com/dotnet/runtime/pull/123593) adds span-based APIs to `IdnMapping` for zero-allocation IDN encoding/decoding. ```csharp namespace System.Globalization @@ -534,420 +159,116 @@ namespace System.Globalization } ``` -### Improvements - -#### Support ICU v78 changes including IDN and Japanese Meiji era start date - -[PR #122480](https://github.com/dotnet/runtime/pull/122480) by @tarekgh - -ICU has released version 78, which includes changes to IDN handling that caused some of our tests to fail when using the updated library. - ---- - -## System.Runtime.InteropServices.JavaScript - -### New Features - -#### [browser][coreCLR] HTTP and WS client implementation in JS - -[PR #123400](https://github.com/dotnet/runtime/pull/123400) by @pavelsavara - -Fixes https://github.com/dotnet/runtime/issues/120216 +These methods throw on invalid input (consistent with existing APIs) and return `false` only when the destination buffer is too small. -#### [browser][coreCLR] implement JS interop - -[PR #123131](https://github.com/dotnet/runtime/pull/123131) by @pavelsavara - -Fixes https://github.com/dotnet/runtime/issues/120703 - ---- - -## Buffers - -### New Features - -#### Add Base64 parity APIs with Base64Url - -[PR #123151](https://github.com/dotnet/runtime/pull/123151) by @stephentoub with GitHub Copilot - -No security vulnerabilities were detected. - -### Improvements - -#### Fix Base64{Url} incorrectly handling small destinations when inputs contain whitespace - -[PR #123223](https://github.com/dotnet/runtime/pull/123223) by @stephentoub with GitHub Copilot - -Base64{Url}.DecodeFromUtf8 and DecodeFromChars incorrectly return DestinationTooSmall when input contains whitespace and destination is small but sufficient for actual data. +Example usage: ```csharp -byte[] input = Encoding.UTF8.GetBytes(" zA== "); -Base64Url.DecodeFromUtf8(input, new byte[5]); // ✓ writes 1 byte -Base64Url.DecodeFromUtf8(input, new byte[1]); // ✗ was: "Destination is too short" +var mapping = new IdnMapping(); +Span buffer = stackalloc char[256]; -Base64Url.DecodeFromChars(new string(' ', 8), new byte[1]); // ✗ was: "Destination is too short" +// Convert Unicode to ASCII (Punycode) +if (mapping.TryGetAscii("münchen.de", buffer, out int charsWritten)) +{ + ReadOnlySpan ascii = buffer.Slice(0, charsWritten); + // ascii contains "xn--mnchen-3ya.de" +} ``` ---- - -## LINQ - -### New Features - -#### Add coalescence optimization for AsyncEnumerable Append/Prepend/Concat operations - -[PR #122389](https://github.com/dotnet/runtime/pull/122389) by @stephentoub with GitHub Copilot +## File.OpenNullHandle for Efficient I/O Redirection -In .NET 10 AsyncEnumerable LINQ features are now included into BCL instead of the standalone package System.Linq.Async. Most things work as expected, but in the scenario of Append followed by a SumAsync we are seeing a regression in performance that is not expected (one of the scenarios we have noted down so far in our internal testing). +[dotnet/runtime #123483](https://github.com/dotnet/runtime/pull/123483) adds `File.OpenNullHandle()` to obtain a handle to the system's null device (`NUL` on Windows, `/dev/null` on Unix). This enables efficient discarding of process output/error streams or providing empty input without the overhead of reading and ignoring data. ```csharp -using BenchmarkDotNet.Attributes; -using BenchmarkDotNet.Running; - -BenchmarkRunner.Run(BenchmarkConverter.TypeToBenchmarks(typeof(AppendTest))); - -[MemoryDiagnoser] -[MinColumn, MaxColumn, Q1Column, Q3Column, AllStatisticsColumn] -[JsonExporterAttribute.Full] -public class AppendTest +namespace System.IO { - [Benchmark] - public async Task AppendInts() + public static class File { - var enumerable = AsyncEnumerable.Empty(); - for (int i = 0; i < 10000; i++) - enumerable = enumerable.Append(i); - - return await enumerable.SumAsync(); + public static SafeFileHandle OpenNullHandle(); } } ``` -#### Add early return in TryGetLast for empty results. - -[PR #123306](https://github.com/dotnet/runtime/pull/123306) by @prozolic - -This PR adds a fast path in IEnumerableSkipTakeIterator.TryGetLast. When source is an Iterator and GetCount(onlyIfCheap: true) returns a valid count (not -1), check if count <= _minIndexInclusive. In this case, immediately return with found=false. - ---- - -## Collections - -### New Features - -#### Add cancellation token check to BlockingCollection.TakeFromAny fast path - -[PR #122410](https://github.com/dotnet/runtime/pull/122410) by @stephentoub with GitHub Copilot - -BlockingCollecction.TakeFromAny do not check state of cancellationToken (3rd argument). +Example usage: ```csharp -var bc1 = new BlockingCollection(); -var bc2 = new BlockingCollection(); -bc1.Add(1); -bc2.Add(2); - -var cts = new CancellationTokenSource(); -cts.Cancel(); - -// Previously: would successfully take item 1 or 2 -// Now: throws OperationCanceledException immediately -BlockingCollection.TakeFromAny(new[] { bc1, bc2 }, out int item, cts.Token); +// Efficiently discard process output +using var nullHandle = File.OpenNullHandle(); +var startInfo = new ProcessStartInfo("myapp.exe") +{ + RedirectStandardOutput = true, + StandardOutputHandle = nullHandle +}; ``` -### Performance +## Standard Handle APIs for Console -#### Optimize HashSet.UnionWith to copy data from another HashSet when empty - -[PR #122952](https://github.com/dotnet/runtime/pull/122952) by @stephentoub with GitHub Copilot - -When UnionWith is called on an empty HashSet with another HashSet that has the same effective comparer, we can use ConstructFrom to copy the internal data structures directly instead of adding each element individually with collision ch +[dotnet/runtime #123478](https://github.com/dotnet/runtime/pull/123478) adds APIs for direct access to standard input/output/error handles. ```csharp -// Before: iterates through all elements, computing hash and checking collisions for each -// After: copies internal arrays directly when destination is empty and comparers match -if (Count == 0 && other is HashSet otherAsSet && EffectiveEqualityComparersAreEqual(this, otherAsSet)) +namespace System { - ConstructFrom(otherAsSet); - return; + public static class Console + { + public static SafeFileHandle OpenStandardInputHandle(); + public static SafeFileHandle OpenStandardOutputHandle(); + public static SafeFileHandle OpenStandardErrorHandle(); + } } ``` ---- - -## System.Formats.Tar - -### New Features - -#### Add tar tests for >8GB file entries using simulated streams - -[PR #123091](https://github.com/dotnet/runtime/pull/123091) by @rzikm with GitHub Copilot +## CancellationToken Overloads for TextWriter -Adds automated tests for tar archives with >8GB file entries using SimulatedDataStream and ConnectedStreams to avoid materializing large data. Previous manual tests required actual disk space and were unsuitable for CI. - -#### Add regression tests for TarReader.GetNextEntry after DataStream disposal - -[PR #122945](https://github.com/dotnet/runtime/pull/122945) by @stephentoub with GitHub Copilot - -> +[dotnet/runtime #122127](https://github.com/dotnet/runtime/pull/122127) adds `CancellationToken` overloads to all `WriteAsync` and `WriteLineAsync` methods on `TextWriter`. ```csharp -> using (var tarReader = new TarReader(unseekableStream)) -> { -> TarEntry? entry; -> while ((entry = tarReader.GetNextEntry()) != null) -> { -> Stream s = entry.DataStream; -> s.CopyTo(someOtherStream); -> s.Dispose(); -> } -> } -> +public abstract class TextWriter +{ + public virtual Task WriteAsync(char value, CancellationToken cancellationToken); + public virtual Task WriteAsync(string? value, CancellationToken cancellationToken); + public virtual Task WriteAsync(char[] buffer, int index, int count, CancellationToken cancellationToken); + public virtual Task WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken); + public virtual Task WriteLineAsync(CancellationToken cancellationToken); + public virtual Task WriteLineAsync(char value, CancellationToken cancellationToken); + public virtual Task WriteLineAsync(string? value, CancellationToken cancellationToken); + public virtual Task WriteLineAsync(char[] buffer, int index, int count, CancellationToken cancellationToken); + public virtual Task WriteLineAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken); +} ``` ---- - -## Numerics - -### New Features - -#### Add SSE implementation to Matrix4x4.GetDeterminant - -[PR #123954](https://github.com/dotnet/runtime/pull/123954) by @alexcovington - -This PR adds an SSE implementation for Matrix4x4.GetDeterminant. Performance improves by about 15% by vectorizing the operations. - ---- - -## Tensor Primitives - -### Performance - -#### Vectorize BitIncrement and BitDecrement for float/double in TensorPrimitives - -[PR #123610](https://github.com/dotnet/runtime/pull/123610) by @stephentoub with GitHub Copilot - -Implements SIMD vectorization for BitIncrement and BitDecrement operations on float and double types in TensorPrimitives. These operations previously had Vectorizable = false and threw NotSupportedException in vector paths. - ---- - -## Microsoft.Extensions.Logging - -### Improvements - -#### FormattedLogValues - Small optimization for index operator - -[PR #122059](https://github.com/dotnet/runtime/pull/122059) by @snakefoot - -Resolves #122046 (Removed "expensive" Count-check, since also exists in LogValuesFormatter) - ---- - -## System.Diagnostics - -### Improvements - -#### [browser][CoreCLR] Trimming feature System.Diagnostics.StackTrace.IsLineNumberSupported - -[PR #123429](https://github.com/dotnet/runtime/pull/123429) by @pavelsavara - -saves 214KB of uncompressed IL from hello world - ---- +## Function Pointer Support in Reflection.Emit -## System.Runtime.InteropServices +Two PRs add support for function pointer types in `System.Reflection.Emit`: -### New Features +- [dotnet/runtime #119935](https://github.com/dotnet/runtime/pull/119935) adds support for creating and working with function pointer types +- [dotnet/runtime #121128](https://github.com/dotnet/runtime/pull/121128) extends support for references to unmanaged function pointers -#### Add AddRef to callee that caches interface ptr +These changes enable more advanced interop scenarios when dynamically generating assemblies. -[PR #122509](https://github.com/dotnet/runtime/pull/122509) by @jtschuster +## SOCKS5h Proxy Support in HttpClient -Callee was missing an AddRef when returning the cached interface pointer. Tests no longer fail on Linux with this change locally. +[dotnet/runtime #123218](https://github.com/dotnet/runtime/pull/123218) adds support for the `socks5h://` proxy scheme in `HttpClient`. Previously, attempts to use this scheme threw `NotSupportedException` with the message "Only the 'http', 'https', 'socks4', 'socks4a' and 'socks5' schemes are allowed for proxies." ---- +The `socks5h://` scheme indicates that DNS resolution should be performed by the proxy server rather than locally. -## System.Runtime.CompilerServices - -### New Features - -#### Adding support for aligning AllocateTypeAssociatedMemory - -[PR #122094](https://github.com/dotnet/runtime/pull/122094) by @tannergooding - -Adding support for aligning AllocateTypeAssociatedMemory - ---- - - -## Threading & Time - -### Performance - -#### Major TimeZone performance improvement with per-year caching - -[PR #119662](https://github.com/dotnet/runtime/pull/119662) by @tarekgh - -A significant rewrite of time zone handling introduces a **per-year cache** for time zone transitions, improving performance for time conversions. The cache stores all transitions for a given year in UTC format, eliminating repeated rule lookups during conversions. - -**Windows Benchmarks:** -``` -BenchmarkDotNet v0.15.2, Windows 11 (10.0.26100.6584/24H2/2024Update/HudsonValley) -11th Gen Intel Core i7-11700 2.50GHz, 1 CPU, 16 logical and 8 physical cores -``` - -| Method | base/diff | Base Median (ns) | Diff Median (ns) | -|---------------------------------------|----------:|-----------------:|-----------------:| -| ConvertTimeFromUtc | 3.93 | 47.97 | 12.21 | -| ConvertTimeUsingLocalDateKind | 3.47 | 66.70 | 19.21 | -| ConvertTimeUsingUnspecifiedDateKind | 3.34 | 63.77 | 19.07 | -| ConvertTimeToUtc | 2.98 | 48.33 | 16.23 | -| DateTimeNow | 2.81 | 54.57 | 19.42 | -| GetUtcOffset | 2.48 | 98.64 | 39.83 | -| ConvertTimeUsingUtcDateKind | 2.39 | 19.66 | 8.23 | - -**Linux Benchmarks (WSL):** -``` -BenchmarkDotNet v0.15.2, Linux Ubuntu 25.04 (Plucky Puffin) -11th Gen Intel Core i7-11700 2.50GHz, 1 CPU, 16 logical and 8 physical cores +```csharp +using var handler = new SocketsHttpHandler(); +handler.Proxy = new WebProxy("socks5h://username:password@proxy.example.com:1080"); +using HttpClient client = new HttpClient(handler); +var response = await client.GetStringAsync("http://example.com"); ``` -| Method | base/diff | Base Median (ns) | Diff Median (ns) | -|---------------------------------------|----------:|-----------------:|-----------------:| -| ConvertTimeToUtc | 4.70 | 63.80 | 13.57 | -| ConvertTimeUsingLocalDateKind | 4.25 | 80.09 | 18.84 | -| ConvertTimeUsingUnspecifiedDateKind | 4.01 | 79.23 | 19.78 | -| ConvertTimeFromUtc | 3.54 | 39.34 | 11.12 | -| DateTimeNow | 3.51 | 50.99 | 14.54 | -| GetUtcOffset | 2.87 | 100.40 | 34.94 | -| ConvertTimeUsingUtcDateKind | 1.64 | 17.60 | 10.73 | - -This change also fixes several correctness issues with time zone handling (fixes #24839, #24277, #25075, #118915, #114476). - - -#### Use QueryUnbiasedInterruptTime for more responsive Windows timer behavior - -[PR #122706](https://github.com/dotnet/runtime/pull/122706) by @tannergooding - -Windows apps can now achieve higher timer responsiveness (sub-millisecond) when they opt-in to higher precision tick times. Previously, Windows was restricted to 10-16ms (typically 15.5ms) responsiveness and did not respect apps which set higher precision tick times, while Unix systems already used more responsive timers like `CLOCK_MONOTONIC_COARSE` and `CLOCK_UPTIME_RAW`. - -This change switches from `GetTickCount64` to `QueryUnbiasedInterruptTime` on Windows, aligning behavior with Unix systems and the OS's own Wait APIs which no longer include sleep/hibernate time in timeout checks. - -**Note:** This is a breaking change - timeouts now exclude time spent in sleep/hibernate states on Windows, matching Unix behavior. - -#### Lazy-initialize DateTimeFormatInfoScanner.m_dateWords - -[PR #123886](https://github.com/dotnet/runtime/pull/123886) by @stephentoub - -Reduces memory allocation for cultures that don't have date words by lazy-initializing the scanner's date words collection. Only a subset of cultures have date words, so this avoids unnecessary allocations for the majority of cases. - -### Improvements - -#### Fix timeout/duration calculations using monotonic time and precise tick accumulation - -[PR #123980](https://github.com/dotnet/runtime/pull/123980) by @MihaZupan with GitHub Copilot - -Fixed socket timeout calculations that incorrectly used `.Milliseconds` (returns component 0-999) instead of `.TotalMilliseconds`. For a 2.5 second duration, `.Milliseconds` returns `500` while `.TotalMilliseconds` returns `2500.0`. Also switched to monotonic time source to avoid issues with system clock adjustments. - ---- - - -## Threading (Additional) - -### New Features - -#### Add generic And and Or methods to System.Threading.Interlocked - -[PR #120978](https://github.com/dotnet/runtime/pull/120978) by @EgorBo with GitHub Copilot - -Adds generic `Interlocked.And` and `Interlocked.Or` methods that work with any enum type or integer type, complementing the existing non-generic overloads. - ---- +## HTTP Automatic Decompression with Zstandard -## JSON Serialization (Additional) - -### New Features - -#### Support IReadOnlyDictionary as JsonExtensionData - -[PR #120636](https://github.com/dotnet/runtime/pull/120636) by @stephentoub with GitHub Copilot - -`[JsonExtensionData]` now supports `IReadOnlyDictionary` in addition to the previously supported mutable dictionary types. - ---- - -## Regular Expressions (Additional) - -### Performance - -#### Optimize regex patterns with both beginning and end anchors for early fail-fast - -[PR #120916](https://github.com/dotnet/runtime/pull/120916) by @stephentoub with GitHub Copilot - -Regex patterns that have both beginning (`^`) and end (`$`) anchors can now fail-fast earlier when the input length doesn't match the expected pattern length. - ---- - -## Reflection.Emit - -### New Features - -#### Support function pointer types in System.Reflection.Emit - -[PR #119935](https://github.com/dotnet/runtime/pull/119935) by @jgh07 - -Adds support for creating and working with function pointer types in the Reflection.Emit API. - -#### Support references to unmanaged function pointers in Reflection.Emit - -[PR #121128](https://github.com/dotnet/runtime/pull/121128) by @jgh07 - -Extends Reflection.Emit to support references to unmanaged function pointers, enabling more advanced interop scenarios. - ---- - -## Networking (Security) - Additional - -### New Features - -#### Add missing TlsAlertMessage members - -[PR #120260](https://github.com/dotnet/runtime/pull/120260) by @rzikm - -Adds missing TLS alert message constants to the `TlsAlertMessage` enum for more complete TLS error handling. - ---- - - -## Compression (Additional) - -### New Features - -#### Implement ZStandard Stream, Encoder, Decoder - -[PR #119575](https://github.com/dotnet/runtime/pull/119575) by @rzikm - -Full implementation of `ZStandardStream` with encoder and decoder support. This complements the `DecompressionMethods.Zstandard` HTTP support with direct streaming APIs for Zstandard compression/decompression. - -#### Add ZipArchiveEntry.Open(FileAccess) overloads - -[PR #122032](https://github.com/dotnet/runtime/pull/122032) by @iremyux - -New overloads `Open(FileAccess)` and `OpenAsync(FileAccess, CancellationToken)` allow specifying read-only access when opening ZIP entries in Update mode. Previously, opening any entry in Update mode would decompress the entire entry into memory even when only reading was needed. +[dotnet/runtime #123531](https://github.com/dotnet/runtime/pull/123531) adds Zstandard compression support to `DecompressionMethods` for automatic HTTP response decompression. ```csharp -// Before: Always loads entire entry into memory in Update mode -using var stream = entry.Open(); +var handler = new HttpClientHandler +{ + AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Zstandard +}; -// After: Can open read-only without loading into memory -using var stream = entry.Open(FileAccess.Read); +using var client = new HttpClient(handler); +// Automatically decompresses zstd-encoded responses +var response = await client.GetAsync("https://example.com"); ``` - -#### Make ZipArchiveEntry.CompressionMethod public - -[PR #122045](https://github.com/dotnet/runtime/pull/122045) by @iremyux - -Exposes the compression method of ZIP archive entries through a new public `ZipCompressionMethod` enum and `CompressionMethod` property on `ZipArchiveEntry`. - ---- - From 91884da39632b9b64ad1a27109f34c43f5a910dd Mon Sep 17 00:00:00 2001 From: Art Leonard Date: Thu, 5 Feb 2026 15:21:07 -0800 Subject: [PATCH 08/11] Reorganize .NET 11 Preview 1 libraries section --- .../11.0/preview/preview1/libraries.md | 136 ++++++++---------- 1 file changed, 56 insertions(+), 80 deletions(-) diff --git a/release-notes/11.0/preview/preview1/libraries.md b/release-notes/11.0/preview/preview1/libraries.md index dd0a2ed850..e05898998c 100644 --- a/release-notes/11.0/preview/preview1/libraries.md +++ b/release-notes/11.0/preview/preview1/libraries.md @@ -3,16 +3,14 @@ .NET 11 Preview 1 includes new .NET Libraries features & enhancements: - [Zstandard Compression Support](#zstandard-compression-support) -- [ZipArchiveEntry.Open with FileAccess Parameter](#ziparchiveentry-open-with-fileaccess-parameter) -- [TimeZone Performance Improvements (per-year caching)](#timezone-performance-improvements) +- [TimeZone Performance Improvements](#timezone-performance-improvements) +- [ZipArchiveEntry.Open with FileAccess Parameter](#ziparchiveentryopen-with-fileaccess-parameter) - [Generic Interlocked.And and Interlocked.Or Methods](#generic-interlockedand-and-interlockedor-methods) - [Span-based IDN APIs for IdnMapping](#span-based-idn-apis-for-idnmapping) -- [File.OpenNullHandle for Efficient I/O Redirection](#fileopennullhandle-for-efficient-io-redirection) -- [Standard Handle APIs for Console](#standard-handle-apis-for-console) - [CancellationToken Overloads for TextWriter](#cancellationtoken-overloads-for-textwriter) +- [Process I/O Improvements](#process-io-improvements) - [Function Pointer Support in Reflection.Emit](#function-pointer-support-in-reflectionemit) - [SOCKS5h Proxy Support in HttpClient](#socks5h-proxy-support-in-httpclient) -- [HTTP Automatic Decompression with Zstandard](#http-automatic-decompression-with-zstandard) .NET Libraries updates in .NET 11: @@ -51,29 +49,25 @@ Usage: using var compressStream = new ZStandardStream(outputStream, CompressionMode.Compress); await inputStream.CopyToAsync(compressStream); -// Decompress data +// Decompress data using var decompressStream = new ZStandardStream(inputStream, CompressionMode.Decompress); await decompressStream.CopyToAsync(outputStream); ``` -## ZipArchiveEntry.Open with FileAccess Parameter - -[dotnet/runtime #122032](https://github.com/dotnet/runtime/pull/122032) adds new overloads to `ZipArchiveEntry.Open()` that accept a `FileAccess` parameter, allowing users to specify the desired access mode when opening an entry stream. +### HTTP Automatic Decompression with Zstandard -When a `ZipArchive` is opened in `ZipArchiveMode.Update`, calling `ZipArchiveEntry.Open()` always returns a read-write stream by invoking `OpenInUpdateMode()`. This causes the entire entry to be decompressed into memory, even when the caller only intends to read the entry's contents. - -New APIs: +[dotnet/runtime #123531](https://github.com/dotnet/runtime/pull/123531) adds Zstandard to `DecompressionMethods` for automatic HTTP response decompression. ```csharp -public Stream Open(FileAccess access); -public Task OpenAsync(FileAccess access, CancellationToken cancellationToken = default); -``` - -Update Mode Details: +var handler = new HttpClientHandler +{ + AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Zstandard +}; -- `FileAccess.Read`: Opens a read-only stream over the entry's compressed data without loading it into memory. Useful for streaming reads. -- `FileAccess.Write`: Opens an empty writable stream, discarding any existing entry data. Semantically equivalent to "replace the entry content entirely" (like `FileMode.Create`). -- `FileAccess.ReadWrite`: Same as parameterless `Open()`/`OpenAsync()` - loads existing data into memory and returns a read/write/seekable stream. +using var client = new HttpClient(handler); +// Automatically decompresses zstd-encoded responses +var response = await client.GetAsync("https://example.com"); +``` ## TimeZone Performance Improvements @@ -115,6 +109,23 @@ BenchmarkDotNet v0.15.2, Linux Ubuntu 25.04 (Plucky Puffin) This change also fixes several correctness issues with time zone handling (fixes #24839, #24277, #25075, #118915, #114476). +## ZipArchiveEntry.Open with FileAccess Parameter + +[dotnet/runtime #122032](https://github.com/dotnet/runtime/pull/122032) adds new overloads to `ZipArchiveEntry.Open()` that accept a `FileAccess` parameter, allowing users to specify the desired access mode when opening an entry stream. + +When a `ZipArchive` is opened in `ZipArchiveMode.Update`, calling `ZipArchiveEntry.Open()` always returns a read-write stream by invoking `OpenInUpdateMode()`. This causes the entire entry to be decompressed into memory, even when the caller only intends to read the entry's contents. + +```csharp +public Stream Open(FileAccess access); +public Task OpenAsync(FileAccess access, CancellationToken cancellationToken = default); +``` + +Update Mode Details: + +- `FileAccess.Read`: Opens a read-only stream over the entry's compressed data without loading it into memory. Useful for streaming reads. +- `FileAccess.Write`: Opens an empty writable stream, discarding any existing entry data. Semantically equivalent to "replace the entry content entirely" (like `FileMode.Create`). +- `FileAccess.ReadWrite`: Same as parameterless `Open()`/`OpenAsync()` - loads existing data into memory and returns a read/write/seekable stream. + ## Generic Interlocked.And and Interlocked.Or Methods [dotnet/runtime #120978](https://github.com/dotnet/runtime/pull/120978) adds generic versions of the `And` and `Or` methods to `System.Threading.Interlocked`, enabling atomic bitwise operations on any enum type or integer type. @@ -129,8 +140,6 @@ public static class Interlocked These methods support all integer primitive types (`byte`, `sbyte`, `short`, `ushort`, `int`, `uint`, `long`, `ulong`, `nint`, `nuint`) and any enum backed by these types. -Example usage: - ```csharp [Flags] enum FilePermissions { None = 0, Read = 1, Write = 2, Execute = 4 } @@ -161,8 +170,6 @@ namespace System.Globalization These methods throw on invalid input (consistent with existing APIs) and return `false` only when the destination buffer is too small. -Example usage: - ```csharp var mapping = new IdnMapping(); Span buffer = stackalloc char[256]; @@ -175,64 +182,48 @@ if (mapping.TryGetAscii("münchen.de", buffer, out int charsWritten)) } ``` -## File.OpenNullHandle for Efficient I/O Redirection +## CancellationToken Overloads for TextWriter -[dotnet/runtime #123483](https://github.com/dotnet/runtime/pull/123483) adds `File.OpenNullHandle()` to obtain a handle to the system's null device (`NUL` on Windows, `/dev/null` on Unix). This enables efficient discarding of process output/error streams or providing empty input without the overhead of reading and ignoring data. +[dotnet/runtime #122127](https://github.com/dotnet/runtime/pull/122127) adds `CancellationToken` overloads to all `WriteAsync` and `WriteLineAsync` methods on `TextWriter`. ```csharp -namespace System.IO +public abstract class TextWriter { - public static class File - { - public static SafeFileHandle OpenNullHandle(); - } + public virtual Task WriteAsync(char value, CancellationToken cancellationToken); + public virtual Task WriteAsync(string? value, CancellationToken cancellationToken); + public virtual Task WriteAsync(char[] buffer, int index, int count, CancellationToken cancellationToken); + public virtual Task WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken); + public virtual Task WriteLineAsync(CancellationToken cancellationToken); + public virtual Task WriteLineAsync(char value, CancellationToken cancellationToken); + public virtual Task WriteLineAsync(string? value, CancellationToken cancellationToken); + public virtual Task WriteLineAsync(char[] buffer, int index, int count, CancellationToken cancellationToken); + public virtual Task WriteLineAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken); } ``` -Example usage: +## Process I/O Improvements -```csharp -// Efficiently discard process output -using var nullHandle = File.OpenNullHandle(); -var startInfo = new ProcessStartInfo("myapp.exe") -{ - RedirectStandardOutput = true, - StandardOutputHandle = nullHandle -}; -``` - -## Standard Handle APIs for Console +### File.OpenNullHandle -[dotnet/runtime #123478](https://github.com/dotnet/runtime/pull/123478) adds APIs for direct access to standard input/output/error handles. +[dotnet/runtime #123483](https://github.com/dotnet/runtime/pull/123483) adds `File.OpenNullHandle()` to obtain a handle to the system's null device (`NUL` on Windows, `/dev/null` on Unix). This enables efficient discarding of process output/error streams or providing empty input without the overhead of reading and ignoring data. ```csharp -namespace System +public static class File { - public static class Console - { - public static SafeFileHandle OpenStandardInputHandle(); - public static SafeFileHandle OpenStandardOutputHandle(); - public static SafeFileHandle OpenStandardErrorHandle(); - } + public static SafeFileHandle OpenNullHandle(); } ``` -## CancellationToken Overloads for TextWriter +### Standard Handle APIs -[dotnet/runtime #122127](https://github.com/dotnet/runtime/pull/122127) adds `CancellationToken` overloads to all `WriteAsync` and `WriteLineAsync` methods on `TextWriter`. +[dotnet/runtime #123478](https://github.com/dotnet/runtime/pull/123478) adds APIs for direct access to standard input/output/error handles. ```csharp -public abstract class TextWriter +public static class Console { - public virtual Task WriteAsync(char value, CancellationToken cancellationToken); - public virtual Task WriteAsync(string? value, CancellationToken cancellationToken); - public virtual Task WriteAsync(char[] buffer, int index, int count, CancellationToken cancellationToken); - public virtual Task WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken); - public virtual Task WriteLineAsync(CancellationToken cancellationToken); - public virtual Task WriteLineAsync(char value, CancellationToken cancellationToken); - public virtual Task WriteLineAsync(string? value, CancellationToken cancellationToken); - public virtual Task WriteLineAsync(char[] buffer, int index, int count, CancellationToken cancellationToken); - public virtual Task WriteLineAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken); + public static SafeFileHandle OpenStandardInputHandle(); + public static SafeFileHandle OpenStandardOutputHandle(); + public static SafeFileHandle OpenStandardErrorHandle(); } ``` @@ -247,28 +238,13 @@ These changes enable more advanced interop scenarios when dynamically generating ## SOCKS5h Proxy Support in HttpClient -[dotnet/runtime #123218](https://github.com/dotnet/runtime/pull/123218) adds support for the `socks5h://` proxy scheme in `HttpClient`. Previously, attempts to use this scheme threw `NotSupportedException` with the message "Only the 'http', 'https', 'socks4', 'socks4a' and 'socks5' schemes are allowed for proxies." +[dotnet/runtime #123218](https://github.com/dotnet/runtime/pull/123218) adds support for the `socks5h://` proxy scheme in `HttpClient`. Previously, attempts to use this scheme threw `NotSupportedException`. The `socks5h://` scheme indicates that DNS resolution should be performed by the proxy server rather than locally. ```csharp using var handler = new SocketsHttpHandler(); -handler.Proxy = new WebProxy("socks5h://username:password@proxy.example.com:1080"); +handler.Proxy = new WebProxy("socks5h://proxy.example.com:1080"); using HttpClient client = new HttpClient(handler); var response = await client.GetStringAsync("http://example.com"); ``` - -## HTTP Automatic Decompression with Zstandard - -[dotnet/runtime #123531](https://github.com/dotnet/runtime/pull/123531) adds Zstandard compression support to `DecompressionMethods` for automatic HTTP response decompression. - -```csharp -var handler = new HttpClientHandler -{ - AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Zstandard -}; - -using var client = new HttpClient(handler); -// Automatically decompresses zstd-encoded responses -var response = await client.GetAsync("https://example.com"); -``` From afaacbd6abbeca56bf370ca555bf7b4ffb8894e9 Mon Sep 17 00:00:00 2001 From: Art Leonard Date: Fri, 6 Feb 2026 10:21:31 -0800 Subject: [PATCH 09/11] Update libraries.md --- .../11.0/preview/preview1/libraries.md | 106 +++++++++--------- 1 file changed, 55 insertions(+), 51 deletions(-) diff --git a/release-notes/11.0/preview/preview1/libraries.md b/release-notes/11.0/preview/preview1/libraries.md index e05898998c..b1036fb3fc 100644 --- a/release-notes/11.0/preview/preview1/libraries.md +++ b/release-notes/11.0/preview/preview1/libraries.md @@ -3,13 +3,17 @@ .NET 11 Preview 1 includes new .NET Libraries features & enhancements: - [Zstandard Compression Support](#zstandard-compression-support) +- [BFloat16 Floating-Point Type](#bfloat16-floating-point-type) - [TimeZone Performance Improvements](#timezone-performance-improvements) - [ZipArchiveEntry.Open with FileAccess Parameter](#ziparchiveentryopen-with-fileaccess-parameter) +- [IReadOnlySet Support in System.Text.Json](#ireadonlyset-support-in-systemtextjson) +- [Base64 Parity with Base64Url](#base64-parity-with-base64url) - [Generic Interlocked.And and Interlocked.Or Methods](#generic-interlockedand-and-interlockedor-methods) - [Span-based IDN APIs for IdnMapping](#span-based-idn-apis-for-idnmapping) - [CancellationToken Overloads for TextWriter](#cancellationtoken-overloads-for-textwriter) - [Process I/O Improvements](#process-io-improvements) - [Function Pointer Support in Reflection.Emit](#function-pointer-support-in-reflectionemit) +- [CGM Extension Support in MediaTypeMap](#cgm-extension-support-in-mediatypemap) - [SOCKS5h Proxy Support in HttpClient](#socks5h-proxy-support-in-httpclient) .NET Libraries updates in .NET 11: @@ -22,25 +26,7 @@ Zstandard offers significantly faster compression and decompression compared to existing algorithms while maintaining competitive compression ratios. -Benchmarks: - -| Method | Level | File | Algorithm | Mean | Size | Compressed | -|----------- |-------- |----------------- |---------- |------------:|-----:|-----:| -| Compress | Optimal | alice29.txt | Brotli | 2,306.40 μs | 148481 | 54517 | -| Compress | Optimal | alice29.txt | Zstandard | 842.743 μs | 148481 | 54919 | -| Compress | Optimal | alice29.txt | Deflate | 2,421.16 μs | 148481 | 53890 | -| | | | | | | | -| Decompress | Optimal | alice29.txt | Brotli | 320.82 μs | -| Decompress | Optimal | alice29.txt | Zstandard | 139.251 μs | -| Decompress | Optimal | alice29.txt | Deflate | 275.43 μs | -| | | | | | | | -| Compress | Fastest | TestDocument.pdf | Brotli | 300.40 μs | 121993 | 117104 | -| Compress | Fastest | TestDocument.pdf | Zstandard | 137.3 μs | 121993 | 119405 | -| Compress | Fastest | TestDocument.pdf | Deflate | 947.61 μs | 121993 | 121404 | -| | | | | | | | -| Decompress | Fastest | TestDocument.pdf | Brotli | 233.14 μs | -| Decompress | Fastest | TestDocument.pdf | Zstandard | 17.22 μs | -| Decompress | Fastest | TestDocument.pdf | Deflate | 238.81 μs | +Benchmarks from [dotnet/runtime #119575](https://github.com/dotnet/runtime/pull/119575) compare Zstandard against Brotli and Deflate across text (alice29.txt, 148 KB) and binary (TestDocument.pdf, 122 KB) workloads from the [Canterbury Corpus](http://corpus.canterbury.ac.nz/descriptions/) at both Optimal and Fastest compression levels. Zstandard compresses 2–7x faster than Brotli and Deflate at Optimal level, and decompresses 2–14x faster at Fastest level, while achieving comparable compression ratios. Usage: @@ -69,43 +55,27 @@ using var client = new HttpClient(handler); var response = await client.GetAsync("https://example.com"); ``` -## TimeZone Performance Improvements +## BFloat16 Floating-Point Type -[dotnet/runtime #119662](https://github.com/dotnet/runtime/pull/119662) introduces a **per-year cache** for time zone transitions, dramatically improving performance for time conversions. The cache stores all transitions for a given year in UTC format, eliminating repeated rule lookups during conversions. +[dotnet/runtime #98643](https://github.com/dotnet/runtime/pull/98643), contributed by community member @huoyaoyuan, adds `System.Numerics.BFloat16`, a 16-bit floating-point type using the "Brain Floating Point" format widely used in machine learning and AI workloads. BFloat16 uses the same number of exponent bits as `float` (8 bits) but with a reduced significand (7 bits), making it ideal for training and inference scenarios where range matters more than precision. -### Windows +`BFloat16` implements all standard numeric interfaces (`INumber`, `IFloatingPoint`, etc.) and supports conversions to and from `float`, `double`, and `Half`. -``` -BenchmarkDotNet v0.15.2, Windows 11 (10.0.26100.6584/24H2/2024Update/HudsonValley) -11th Gen Intel Core i7-11700 2.50GHz, 1 CPU, 16 logical and 8 physical cores -``` +```csharp +BFloat16 value = (BFloat16)3.14f; +float asFloat = (float)value; // Lossless upcast to float -| Faster | base/diff | Base Median (ns) | Diff Median (ns) | -| ---------------------------------------------------- | ---------:| ----------------:| ----------------:| -| Baseline.Program.ConvertTimeFromUtc | 3.93 | 47.97 | 12.21 | -| Baseline.Program.ConvertTimeUsingLocalDateKind | 3.47 | 66.70 | 19.21 | -| Baseline.Program.ConvertTimeUsingUnspecifiedDateKind | 3.34 | 63.77 | 19.07 | -| Baseline.Program.ConvertTimeToUtc | 2.98 | 48.33 | 16.23 | -| Baseline.Program.DateTimeNow | 2.81 | 54.57 | 19.42 | -| Baseline.Program.GetUtcOffset | 2.48 | 98.64 | 39.83 | -| Baseline.Program.ConvertTimeUsingUtcDateKind | 2.39 | 19.66 | 8.23 | +// Use in ML-style computation +BFloat16 a = (BFloat16)1.5f; +BFloat16 b = (BFloat16)2.0f; +BFloat16 result = a * b; // 3.0 +``` -### Linux (WSL) +## TimeZone Performance Improvements -``` -BenchmarkDotNet v0.15.2, Linux Ubuntu 25.04 (Plucky Puffin) -11th Gen Intel Core i7-11700 2.50GHz, 1 CPU, 16 logical and 8 physical cores -``` +[dotnet/runtime #119662](https://github.com/dotnet/runtime/pull/119662) introduces a **per-year cache** for time zone transitions, dramatically improving performance for time conversions. The cache stores all transitions for a given year in UTC format, eliminating repeated rule lookups during conversions. -| Faster | base/diff | Base Median (ns) | Diff Median (ns) | -| ---------------------------------------------------- | ---------:| ----------------:| ----------------:| -| Baseline.Program.ConvertTimeToUtc | 4.70 | 63.80 | 13.57 | -| Baseline.Program.ConvertTimeUsingLocalDateKind | 4.25 | 80.09 | 18.84 | -| Baseline.Program.ConvertTimeUsingUnspecifiedDateKind | 4.01 | 79.23 | 19.78 | -| Baseline.Program.ConvertTimeFromUtc | 3.54 | 39.34 | 11.12 | -| Baseline.Program.DateTimeNow | 3.51 | 50.99 | 14.54 | -| Baseline.Program.GetUtcOffset | 2.87 | 100.40 | 34.94 | -| Baseline.Program.ConvertTimeUsingUtcDateKind | 1.64 | 17.60 | 10.73 | +Benchmarks from [dotnet/runtime #119662](https://github.com/dotnet/runtime/pull/119662) measured seven common time zone operations (`ConvertTimeFromUtc`, `ConvertTimeToUtc`, `DateTimeNow`, `GetUtcOffset`, and three `ConvertTime` variants with different `DateTimeKind` values) on Windows 11 and Linux (WSL) using an 11th Gen Intel Core i7-11700. On Windows, operations are 2.4–3.9x faster (e.g. `ConvertTimeFromUtc` dropped from 48.0 ns to 12.2 ns). On Linux, improvements are even larger at 1.6–4.7x (e.g. `ConvertTimeToUtc` dropped from 63.8 ns to 13.6 ns). This change also fixes several correctness issues with time zone handling (fixes #24839, #24277, #25075, #118915, #114476). @@ -126,6 +96,38 @@ Update Mode Details: - `FileAccess.Write`: Opens an empty writable stream, discarding any existing entry data. Semantically equivalent to "replace the entry content entirely" (like `FileMode.Create`). - `FileAccess.ReadWrite`: Same as parameterless `Open()`/`OpenAsync()` - loads existing data into memory and returns a read/write/seekable stream. +## IReadOnlySet Support in System.Text.Json + +[dotnet/runtime #120306](https://github.com/dotnet/runtime/pull/120306), contributed by community member @sander1095, adds support for serializing and deserializing `IReadOnlySet` collections in `System.Text.Json`. Previously, only `ISet` and concrete set types like `HashSet` were supported. This aligns the library's handling of `IReadOnlySet` with other collection interfaces like `ISet` and `ICollection`. + +```csharp +// Now works - previously threw NotSupportedException +IReadOnlySet tags = new HashSet { "dotnet", "csharp" }; +string json = JsonSerializer.Serialize(tags); +IReadOnlySet deserialized = JsonSerializer.Deserialize>(json); +``` + +## Base64 Parity with Base64Url + +[dotnet/runtime #123151](https://github.com/dotnet/runtime/pull/123151) adds UTF-16 encoding/decoding APIs to `System.Buffers.Text.Base64` that previously only existed on `Base64Url`. The `Base64Url` class introduced a much nicer API surface (with `OperationStatus` returns, `EncodeToString`, `DecodeFromChars`, etc.) that standard `Base64` lacked, forcing developers to use the less capable `Convert` class for standard Base64 operations. + +```csharp +namespace System.Buffers.Text; + +public static partial class Base64 +{ + // New APIs matching Base64Url surface + public static byte[] DecodeFromChars(ReadOnlySpan source); + public static OperationStatus DecodeFromChars(ReadOnlySpan source, Span destination, + out int charsConsumed, out int bytesWritten, bool isFinalBlock = true); + public static string EncodeToString(ReadOnlySpan source); + public static char[] EncodeToChars(ReadOnlySpan source); + public static int GetEncodedLength(int bytesLength); + public static int GetMaxDecodedLength(int base64Length); + // ... and more +} +``` + ## Generic Interlocked.And and Interlocked.Or Methods [dotnet/runtime #120978](https://github.com/dotnet/runtime/pull/120978) adds generic versions of the `And` and `Or` methods to `System.Threading.Interlocked`, enabling atomic bitwise operations on any enum type or integer type. @@ -168,8 +170,6 @@ namespace System.Globalization } ``` -These methods throw on invalid input (consistent with existing APIs) and return `false` only when the destination buffer is too small. - ```csharp var mapping = new IdnMapping(); Span buffer = stackalloc char[256]; @@ -236,6 +236,10 @@ Two PRs add support for function pointer types in `System.Reflection.Emit`: These changes enable more advanced interop scenarios when dynamically generating assemblies. +## CGM Extension Support in MediaTypeMap + +[dotnet/runtime #122591](https://github.com/dotnet/runtime/pull/122591) adds the `.cgm` (Computer Graphics Metafile, ISO 8632) extension to `MediaTypeMap` with the IANA-registered MIME type `image/cgm`. Applications using `MediaTypeMap` to resolve `.cgm` files will now correctly identify them instead of returning null. CGM is still actively used in technical documentation, engineering, and aviation industry applications. + ## SOCKS5h Proxy Support in HttpClient [dotnet/runtime #123218](https://github.com/dotnet/runtime/pull/123218) adds support for the `socks5h://` proxy scheme in `HttpClient`. Previously, attempts to use this scheme threw `NotSupportedException`. From 381101005f8868ac58a726cd4cacc0f5a3909941 Mon Sep 17 00:00:00 2001 From: Jeff Handley Date: Sun, 8 Feb 2026 05:04:51 -0800 Subject: [PATCH 10/11] Add more libraries features based on the .NET 10.0 GA to .NET 11 Preview 1 API Diff --- .../11.0/preview/preview1/libraries.md | 254 ++++++++++++++++-- 1 file changed, 233 insertions(+), 21 deletions(-) diff --git a/release-notes/11.0/preview/preview1/libraries.md b/release-notes/11.0/preview/preview1/libraries.md index b1036fb3fc..d479ff23b3 100644 --- a/release-notes/11.0/preview/preview1/libraries.md +++ b/release-notes/11.0/preview/preview1/libraries.md @@ -4,11 +4,18 @@ - [Zstandard Compression Support](#zstandard-compression-support) - [BFloat16 Floating-Point Type](#bfloat16-floating-point-type) -- [TimeZone Performance Improvements](#timezone-performance-improvements) -- [ZipArchiveEntry.Open with FileAccess Parameter](#ziparchiveentryopen-with-fileaccess-parameter) +- [ZipArchiveEntry Improvements](#ziparchiveentry-improvements) +- [FrozenDictionary Collection Expression Support](#frozendictionary-collection-expression-support) +- [TimeZone Improvements](#timezone-improvements) +- [Rune Support Across String, StringBuilder, and TextWriter](#rune-support-across-string-stringbuilder-and-textwriter) +- [MediaTypeMap for MIME Type Lookups](#mediatypemap-for-mime-type-lookups) +- [HMAC and KMAC Verification APIs](#hmac-and-kmac-verification-apis) +- [Hard Link Creation APIs](#hard-link-creation-apis) +- [DivisionRounding for Integer Division Modes](#divisionrounding-for-integer-division-modes) - [IReadOnlySet Support in System.Text.Json](#ireadonlyset-support-in-systemtextjson) - [Base64 Parity with Base64Url](#base64-parity-with-base64url) - [Generic Interlocked.And and Interlocked.Or Methods](#generic-interlockedand-and-interlockedor-methods) +- [Happy Eyeballs Support in Socket.ConnectAsync](#happy-eyeballs-support-in-socketconnectasync) - [Span-based IDN APIs for IdnMapping](#span-based-idn-apis-for-idnmapping) - [CancellationToken Overloads for TextWriter](#cancellationtoken-overloads-for-textwriter) - [Process I/O Improvements](#process-io-improvements) @@ -22,24 +29,40 @@ ## Zstandard Compression Support -[dotnet/runtime #119575](https://github.com/dotnet/runtime/pull/119575) adds native Zstandard (zstd) compression support to .NET through the new `ZStandardStream` class, `ZStandardEncoder`, and `ZStandardDecoder`. +[dotnet/runtime #119575](https://github.com/dotnet/runtime/pull/119575) adds native Zstandard (zstd) compression support to .NET through the new `ZstandardStream` class, `ZstandardEncoder`, and `ZstandardDecoder`. -Zstandard offers significantly faster compression and decompression compared to existing algorithms while maintaining competitive compression ratios. +Zstandard offers significantly faster compression and decompression compared to existing algorithms while maintaining competitive compression ratios. The new APIs include a full set of streaming, one-shot, and dictionary-based compression and decompression capabilities. Benchmarks from [dotnet/runtime #119575](https://github.com/dotnet/runtime/pull/119575) compare Zstandard against Brotli and Deflate across text (alice29.txt, 148 KB) and binary (TestDocument.pdf, 122 KB) workloads from the [Canterbury Corpus](http://corpus.canterbury.ac.nz/descriptions/) at both Optimal and Fastest compression levels. Zstandard compresses 2–7x faster than Brotli and Deflate at Optimal level, and decompresses 2–14x faster at Fastest level, while achieving comparable compression ratios. -Usage: - ```csharp -// Compress data -using var compressStream = new ZStandardStream(outputStream, CompressionMode.Compress); +// Compress data using ZstandardStream +using var compressStream = new ZstandardStream(outputStream, CompressionMode.Compress); await inputStream.CopyToAsync(compressStream); // Decompress data -using var decompressStream = new ZStandardStream(inputStream, CompressionMode.Decompress); +using var decompressStream = new ZstandardStream(inputStream, CompressionMode.Decompress); await decompressStream.CopyToAsync(outputStream); ``` +Advanced usage with `ZstandardEncoder` and `ZstandardDecoder` provides fine-grained control over compression parameters, including quality level, window size, dictionary-based compression, and checksum appending: + +```csharp +// One-shot compression with quality settings +var encoder = new ZstandardEncoder(quality: 5, windowLog: 22); +// ... use encoder.Compress() for incremental compression + +// Configure with options +var options = new ZstandardCompressionOptions +{ + Quality = 5, + WindowLog = 22, + AppendChecksum = true, + EnableLongDistanceMatching = true +}; +using var stream = new ZstandardStream(outputStream, options); +``` + ### HTTP Automatic Decompression with Zstandard [dotnet/runtime #123531](https://github.com/dotnet/runtime/pull/123531) adds Zstandard to `DecompressionMethods` for automatic HTTP response decompression. @@ -59,7 +82,7 @@ var response = await client.GetAsync("https://example.com"); [dotnet/runtime #98643](https://github.com/dotnet/runtime/pull/98643), contributed by community member @huoyaoyuan, adds `System.Numerics.BFloat16`, a 16-bit floating-point type using the "Brain Floating Point" format widely used in machine learning and AI workloads. BFloat16 uses the same number of exponent bits as `float` (8 bits) but with a reduced significand (7 bits), making it ideal for training and inference scenarios where range matters more than precision. -`BFloat16` implements all standard numeric interfaces (`INumber`, `IFloatingPoint`, etc.) and supports conversions to and from `float`, `double`, and `Half`. +`BFloat16` implements all standard numeric interfaces (`INumber`, `IFloatingPoint`, `IBinaryFloatingPointIeee754`, etc.) and supports conversions to and from `float`, `double`, and `Half`. Supporting APIs are also added across the platform, including `BitConverter`, `BinaryPrimitives`, `BigInteger`, `Complex`, and all `Vector` types (`Vector64`, `Vector128`, `Vector256`, `Vector512`). ```csharp BFloat16 value = (BFloat16)3.14f; @@ -69,32 +92,205 @@ float asFloat = (float)value; // Lossless upcast to float BFloat16 a = (BFloat16)1.5f; BFloat16 b = (BFloat16)2.0f; BFloat16 result = a * b; // 3.0 + +// Binary serialization with BinaryPrimitives +Span buffer = stackalloc byte[2]; +BinaryPrimitives.WriteBFloat16LittleEndian(buffer, value); +BFloat16 read = BinaryPrimitives.ReadBFloat16LittleEndian(buffer); +``` + +## ZipArchiveEntry Improvements + +### Open with FileAccess Parameter + +[dotnet/runtime #122032](https://github.com/dotnet/runtime/pull/122032) adds new overloads to `ZipArchiveEntry.Open()` that accept a `FileAccess` parameter, allowing users to specify the desired access mode when opening an entry stream. + +When a `ZipArchive` is opened in `ZipArchiveMode.Update`, calling `ZipArchiveEntry.Open()` always returns a read-write stream that loads the entire entry into memory. The new overload lets you open entries in read-only mode for streaming without the memory overhead. + +```csharp +using var archive = ZipFile.Open("archive.zip", ZipArchiveMode.Update); +var entry = archive.GetEntry("large-file.dat"); + +// Read-only: streams compressed data without loading into memory +using var readStream = entry.Open(FileAccess.Read); + +// Write-only: replaces entry content entirely +using var writeStream = entry.Open(FileAccess.Write); + +// Async overload also available +using var asyncStream = await entry.OpenAsync(FileAccess.Read); +``` + +### ZipCompressionMethod Property + +[dotnet/runtime #95909](https://github.com/dotnet/runtime/issues/95909) exposes the `CompressionMethod` property on `ZipArchiveEntry` and adds the `ZipCompressionMethod` enum. This enables applications to determine the compression algorithm used for each entry without having to compare `CompressedLength` against `Length` as a heuristic. + +```csharp +using var archive = ZipFile.Open("archive.zip", ZipArchiveMode.Read); +foreach (var entry in archive.Entries) +{ + if (entry.CompressionMethod == ZipCompressionMethod.Stored) + { + Console.WriteLine($"{entry.FullName} is stored without compression"); + } +} ``` -## TimeZone Performance Improvements +## FrozenDictionary Collection Expression Support + +[dotnet/runtime #114090](https://github.com/dotnet/runtime/issues/114090) adds the `[CollectionBuilder]` attribute to `FrozenDictionary`, enabling construction from C# [dictionary expressions](https://github.com/dotnet/csharplang/blob/main/proposals/dictionary-expressions.md). This follows the pattern established for `FrozenSet` and `ImmutableDictionary` in earlier releases. + +```csharp +// Create a FrozenDictionary using dictionary expression syntax +FrozenDictionary lookup = [with(StringComparer.Ordinal), "one":1, "two":2, "three":3]; +``` + +## TimeZone Improvements [dotnet/runtime #119662](https://github.com/dotnet/runtime/pull/119662) introduces a **per-year cache** for time zone transitions, dramatically improving performance for time conversions. The cache stores all transitions for a given year in UTC format, eliminating repeated rule lookups during conversions. Benchmarks from [dotnet/runtime #119662](https://github.com/dotnet/runtime/pull/119662) measured seven common time zone operations (`ConvertTimeFromUtc`, `ConvertTimeToUtc`, `DateTimeNow`, `GetUtcOffset`, and three `ConvertTime` variants with different `DateTimeKind` values) on Windows 11 and Linux (WSL) using an 11th Gen Intel Core i7-11700. On Windows, operations are 2.4–3.9x faster (e.g. `ConvertTimeFromUtc` dropped from 48.0 ns to 12.2 ns). On Linux, improvements are even larger at 1.6–4.7x (e.g. `ConvertTimeToUtc` dropped from 63.8 ns to 13.6 ns). -This change also fixes several correctness issues with time zone handling (fixes #24839, #24277, #25075, #118915, #114476). +The new caching approach also replaces the legacy rule-based conversion path—which had accumulated many incremental patches over the years—with a simplified lookup, fixing several correctness issues where time zone conversions returned incorrect results (fixes #24839, #24277, #25075, #118915, #114476). -## ZipArchiveEntry.Open with FileAccess Parameter +## Rune Support Across String, StringBuilder, and TextWriter -[dotnet/runtime #122032](https://github.com/dotnet/runtime/pull/122032) adds new overloads to `ZipArchiveEntry.Open()` that accept a `FileAccess` parameter, allowing users to specify the desired access mode when opening an entry stream. +[dotnet/runtime #27912](https://github.com/dotnet/runtime/issues/27912) flows `System.Text.Rune` through many more APIs across `String`, `StringBuilder`, `TextWriter`, `TextInfo`, and `Char`. This long-requested enhancement makes it significantly easier for applications to work with Unicode text correctly, particularly for characters outside the Basic Multilingual Plane that require surrogate pairs when represented as `char`. -When a `ZipArchive` is opened in `ZipArchiveMode.Update`, calling `ZipArchiveEntry.Open()` always returns a read-write stream by invoking `OpenInUpdateMode()`. This causes the entire entry to be decompressed into memory, even when the caller only intends to read the entry's contents. +### String + +New `Rune`-based overloads have been added for searching, replacing, splitting, and trimming: ```csharp -public Stream Open(FileAccess access); -public Task OpenAsync(FileAccess access, CancellationToken cancellationToken = default); +string text = "Hello 🌍 World"; +Rune globe = new Rune(0x1F30D); // 🌍 + +bool contains = text.Contains(globe); // true +int index = text.IndexOf(globe); // 6 +bool starts = text.StartsWith(globe); // false +string replaced = text.Replace(globe, new Rune('X')); // "Hello X World" +string[] parts = text.Split(globe); // ["Hello ", " World"] +string trimmed = text.Trim(globe); ``` -Update Mode Details: +Additionally, `Char.Equals(char, StringComparison)` and `String.StartsWith(char, StringComparison)` / `String.EndsWith(char, StringComparison)` overloads fill gaps that previously existed only for `string` parameters. + +### StringBuilder + +`StringBuilder` gains `Rune`-aware methods for appending, inserting, replacing, and enumerating: -- `FileAccess.Read`: Opens a read-only stream over the entry's compressed data without loading it into memory. Useful for streaming reads. -- `FileAccess.Write`: Opens an empty writable stream, discarding any existing entry data. Semantically equivalent to "replace the entry content entirely" (like `FileMode.Create`). -- `FileAccess.ReadWrite`: Same as parameterless `Open()`/`OpenAsync()` - loads existing data into memory and returns a read/write/seekable stream. +```csharp +var sb = new StringBuilder("Hello "); +sb.Append(new Rune(0x1F30D)); // Append 🌍 +Rune r = sb.GetRuneAt(6); // Get the Rune at index 6 +sb.Replace(new Rune(0x1F30D), new Rune('X')); + +// Enumerate Runes in StringBuilder +foreach (Rune rune in sb.EnumerateRunes()) +{ + Console.Write(rune); +} +``` + +### RunePosition + +The new `RunePosition` struct and its `Utf16Enumerator`/`Utf8Enumerator` provide position-aware Rune enumeration over spans, including information about whether a replacement character was substituted for invalid data: + +```csharp +ReadOnlySpan text = "Hello 🌍"; +foreach (RunePosition pos in RunePosition.EnumerateUtf16(text)) +{ + Console.WriteLine($"Rune: {pos.Rune}, Start: {pos.StartIndex}, Length: {pos.Length}"); +} +``` + +### TextWriter and TextInfo + +`TextWriter` gains `Write(Rune)`, `WriteAsync(Rune)`, `WriteLine(Rune)`, and `WriteLineAsync(Rune)` methods. `TextInfo` adds `ToLower(Rune)` and `ToUpper(Rune)` for culture-aware casing. + +## MediaTypeMap for MIME Type Lookups + +[dotnet/runtime #121017](https://github.com/dotnet/runtime/issues/121017) adds `System.Net.Mime.MediaTypeMap`, a built-in API for mapping between file extensions and MIME/media types. Previously, developers had to re-create this mapping themselves or rely on third-party packages. The new API supports all IANA-registered mappings plus common ones from Apache mime.types. + +```csharp +using System.Net.Mime; + +// Get MIME type from file extension +string? mediaType = MediaTypeMap.GetMediaType(".json"); // "application/json" +string? pngType = MediaTypeMap.GetMediaType("image.png"); // "image/png" + +// Get file extension from MIME type +string? ext = MediaTypeMap.GetExtension("application/pdf"); // ".pdf" + +// Also works with ReadOnlySpan +ReadOnlySpan path = "/files/document.pdf"; +string? type = MediaTypeMap.GetMediaType(path); +``` + +## HMAC and KMAC Verification APIs + +[dotnet/runtime #116028](https://github.com/dotnet/runtime/issues/116028) adds `Verify` methods to all HMAC classes (`HMACSHA256`, `HMACSHA384`, `HMACSHA512`, `HMACSHA1`, `HMACMD5`, `HMACSHA3_256`, `HMACSHA3_384`, `HMACSHA3_512`), all KMAC classes (`Kmac128`, `Kmac256`, `KmacXof128`, `KmacXof256`), `IncrementalHash`, and `CryptographicOperations`. + +HMAC values often need to be compared in fixed (constant) time to prevent timing attacks. Previously, this required two steps: computing the HMAC with `HashData`, then comparing with `CryptographicOperations.FixedTimeEquals`. This two-step pattern was error-prone — developers often accidentally used LINQ's `SequenceEqual` or similar non-constant-time comparisons. The new `Verify` methods combine both steps into a single, safe call. + +```csharp +// Before: error-prone two-step pattern +byte[] computed = HMACSHA256.HashData(key, data); +bool valid = CryptographicOperations.FixedTimeEquals(computed, expectedHash); + +// After: single-step verification (always constant-time) +bool valid = HMACSHA256.Verify(key, data, expectedHash); + +// Stream-based and async overloads are also available +bool validStream = await HMACSHA256.VerifyAsync(key, dataStream, expectedHash); + +// Algorithm-agnostic verification via CryptographicOperations +bool result = CryptographicOperations.VerifyHmac( + HashAlgorithmName.SHA256, key, data, expectedHash); +``` + +## Hard Link Creation APIs + +[dotnet/runtime #69030](https://github.com/dotnet/runtime/issues/69030) adds `File.CreateHardLink` and `FileInfo.CreateAsHardLink` for creating hard links. Since .NET 6, `File.CreateSymbolicLink` has been available, but symbolic links typically require administrator privileges on Windows, whereas hard links do not. Hard links point to the same file data on disk (same inode on Unix, same MFT entry on Windows) and cannot span volumes, making them less of a security risk. + +```csharp +// Create a hard link from File static method +FileSystemInfo link = File.CreateHardLink("./link.txt", "./original.txt"); + +// Create a hard link from FileInfo instance +var fileInfo = new FileInfo("./original.txt"); +fileInfo.CreateAsHardLink("./link.txt"); +``` + +## DivisionRounding for Integer Division Modes + +[dotnet/runtime #93568](https://github.com/dotnet/runtime/issues/93568) adds support for alternative rounding modes in integer division through the new `DivisionRounding` enum and new methods on `IBinaryInteger`: `Divide`, `DivRem`, and `Remainder`. + +Most hardware implements truncated division (`/` and `%` in C#), but different languages and problem domains require floored, ceiling, Euclidean, or away-from-zero rounding. While computing any of these is fairly trivial, the most efficient implementation is often non-obvious. These new APIs let developers pick the right mode for their scenario with a well-optimized implementation. + +```csharp +// Standard C# division is truncated: -7 / 2 = -3 +int truncated = int.Divide(-7, 2, DivisionRounding.Truncate); // -3 + +// Floored division: rounds towards -infinity +int floored = int.Divide(-7, 2, DivisionRounding.Floor); // -4 + +// Euclidean remainder: always non-negative +int euclideanRem = int.Remainder(-7, 3, DivisionRounding.Euclidean); // 2 + +// Get both quotient and remainder at once +var (q, r) = int.DivRem(-7, 2, DivisionRounding.Floor); // q=-4, r=1 +``` + +The `DivisionRounding` enum supports five modes: + +| Mode | Description | +|---|---| +| `Truncate` | Towards zero (default C# behavior) | +| `Floor` | Towards negative infinity | +| `Ceiling` | Towards positive infinity | +| `AwayFromZero` | Away from zero | +| `Euclidean` | floor(x / abs(n)) * sign(n) | ## IReadOnlySet Support in System.Text.Json @@ -155,6 +351,22 @@ Interlocked.Or(ref permissions, FilePermissions.Write); Interlocked.And(ref permissions, ~FilePermissions.Execute); ``` +## Happy Eyeballs Support in Socket.ConnectAsync + +[dotnet/runtime #87932](https://github.com/dotnet/runtime/issues/87932) implements [RFC 8305 "Happy Eyeballs"](https://www.rfc-editor.org/rfc/rfc8305) support in `Socket.ConnectAsync` through the new `ConnectAlgorithm` enum. Happy Eyeballs improves connection latency by making A and AAAA DNS requests in parallel and alternating connection attempts between IPv4 and IPv6 addresses. + +```csharp +var e = new SocketAsyncEventArgs(); +e.RemoteEndPoint = new DnsEndPoint("example.com", 443); + +// Use Happy Eyeballs algorithm for faster dual-stack connections +Socket.ConnectAsync( + SocketType.Stream, + ProtocolType.Tcp, + e, + ConnectAlgorithm.Parallel); +``` + ## Span-based IDN APIs for IdnMapping [dotnet/runtime #123593](https://github.com/dotnet/runtime/pull/123593) adds span-based APIs to `IdnMapping` for zero-allocation IDN encoding/decoding. From 48f74dc6299d5f8c310b06037d868d299e1fed74 Mon Sep 17 00:00:00 2001 From: artl Date: Mon, 9 Feb 2026 12:23:02 -0800 Subject: [PATCH 11/11] Add Performance Improvements section to libraries.md --- .../11.0/preview/preview1/libraries.md | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/release-notes/11.0/preview/preview1/libraries.md b/release-notes/11.0/preview/preview1/libraries.md index d479ff23b3..9f3ea14e9d 100644 --- a/release-notes/11.0/preview/preview1/libraries.md +++ b/release-notes/11.0/preview/preview1/libraries.md @@ -22,6 +22,7 @@ - [Function Pointer Support in Reflection.Emit](#function-pointer-support-in-reflectionemit) - [CGM Extension Support in MediaTypeMap](#cgm-extension-support-in-mediatypemap) - [SOCKS5h Proxy Support in HttpClient](#socks5h-proxy-support-in-httpclient) +- [Performance Improvements](#performance-improvements) .NET Libraries updates in .NET 11: @@ -464,3 +465,35 @@ handler.Proxy = new WebProxy("socks5h://proxy.example.com:1080"); using HttpClient client = new HttpClient(handler); var response = await client.GetStringAsync("http://example.com"); ``` + +## Performance Improvements + +### Guid.NewGuid() ~10x Faster on Linux + +[dotnet/runtime #123540](https://github.com/dotnet/runtime/pull/123540) speeds up `Guid.NewGuid()` on Linux by switching from `/dev/urandom` reads to the `getrandom()` syscall and by batching and caching GUIDs. The result is a ~10x improvement: from 614.2 ns to 61.16 ns per call. Contributed by community member @reedz. + +### BigInteger Toom-Cook Multiplication + +[dotnet/runtime #112876](https://github.com/dotnet/runtime/pull/112876) upgrades `BigInteger.Multiply` to use the Toom-Cook 3-way algorithm for large operands, reducing time complexity from O(n^1.58) (Karatsuba) to O(n^1.46). For very large multiplications, this yields measurable improvements — e.g., a multiplication that previously took 750 μs now completes in 690 μs, with the gap widening as digit counts increase. Contributed by community member @kzrnm. + +### Vectorized BitIncrement/BitDecrement in TensorPrimitives + +[dotnet/runtime #123610](https://github.com/dotnet/runtime/pull/123610) adds SIMD vectorization for `TensorPrimitives.BitIncrement` and `TensorPrimitives.BitDecrement` on `float` and `double`. Previously these operations were scalar-only. + +| Type | Before | After | Improvement | +|--------|--------------|----------|-------------| +| float | 848.3 ns | 227.8 ns | 3.7x faster | +| double | 1,691.5 ns | 445.4 ns | 3.8x faster | + +### Directory.GetFiles OS-Level Pattern Filtering on Windows + +[dotnet/runtime #122947](https://github.com/dotnet/runtime/pull/122947) optimizes `Directory.GetFiles` on Windows by passing safe search patterns directly to `NtQueryDirectoryFile` as a pre-filter hint, enabling the NTFS B-tree to seek efficiently. For patterns like `"A14881*.jpg"` in a directory with 140,000 files but only 4 matches, this reduces the operation from scanning all 140K entries to returning ~4–10 entries. The managed `MatchesPattern` filter still runs afterward to ensure identical behavior. + +### BitArray.PopCount + +[dotnet/runtime #119804](https://github.com/dotnet/runtime/pull/119804) adds `BitArray.PopCount()`, which returns the number of set bits using hardware-accelerated population count instructions. Contributed by community member @huoyaoyuan. + +```csharp +var bits = new BitArray(new[] { true, false, true, true, false }); +int count = bits.PopCount(); // 3 +```