-
Notifications
You must be signed in to change notification settings - Fork 15.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Performance optimization extension for
RepeatedField<T>
(#19115)
.NET 8 added support for `AddRange` using the `ReadOnlySpan<T>` data structure. This can significantly improve the performance of `RepeatedField<T>` when adding multiple elements and can avoid the potential need to create extra arrays when using spans. Here is the code that was added to .NET to support `AddRange` on `List<T>`: https://github.com/dotnet/runtime/blob/85f6d2d9449fb438cd8a5ca41d4beb4c657594e9/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/CollectionExtensions.cs#L85-L103 In the current implementation of `RepeatedField<T>`, the `AddRange` method only operates on `IEnumerable<T>`. Unfortunately, this means that the callers using `Span<T>` have to copy the content of the span to an array or to some other `IEnumerbale<T>` before calling `AddRange`. This is an expensive operation and can be avoided by adding support for `AddRange` that takes a `ReadOnlySpan<T>` directly. In this proposal, `AddRange` is added as an extension method instead of directly adding it to `RepeatedField<T>` because we want to avoid ambiguity between `RepeatedField<T>.AddRange(IEnumerbale<T>)` and `RepeatedField<T>.AddRange(Span<T>)` for types such as `T[]`. This is the same exact approach taken by .NET runtime itself. Closes #19115 COPYBARA_INTEGRATE_REVIEW=#19115 from prezaei:pedramr/repeated-field-extensions 8d0ac6a PiperOrigin-RevId: 700357702
- Loading branch information
1 parent
343a3f9
commit 70730f5
Showing
3 changed files
with
113 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
#region Copyright notice and license | ||
// Protocol Buffers - Google's data interchange format | ||
// Copyright 2015 Google Inc. All rights reserved. | ||
// | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file or at | ||
// https://developers.google.com/open-source/licenses/bsd | ||
#endregion | ||
|
||
using System; | ||
using System.Security; | ||
using Google.Protobuf.Collections; | ||
|
||
// Note: The choice of the namespace here is important because it's rare that people will directly reference Google.Protobuf.Collections | ||
// in their app as they're typically using collections created by generated code. We are keeping the extension method in the Google.Protobuf | ||
// namespace so that it is discoverable by most users. | ||
|
||
namespace Google.Protobuf | ||
{ | ||
/// <summary> | ||
/// A set of extension methods on <see cref="RepeatedField{T}"/> | ||
/// </summary> | ||
public static class RepeatedFieldExtensions | ||
{ | ||
// Note: This method is an extension method to avoid ambiguous overload conflict with existing AddRange(IEnumerable<T>) when the source is an array. | ||
/// <summary>Adds the elements of the specified span to the end of the <see cref="RepeatedField{T}"/>.</summary> | ||
/// <typeparam name="T">The type of elements in the <see cref="RepeatedField{T}"/>.</typeparam> | ||
/// <param name="repeatedField">The list to which the elements should be added.</param> | ||
/// <param name="source">The span whose elements should be added to the end of the <see cref="RepeatedField{T}"/>.</param> | ||
/// <exception cref="ArgumentNullException">The <paramref name="repeatedField"/> is null.</exception> | ||
[SecuritySafeCritical] | ||
public static void AddRange<T>(this RepeatedField<T> repeatedField, ReadOnlySpan<T> source) | ||
{ | ||
ProtoPreconditions.CheckNotNull(repeatedField, nameof(repeatedField)); | ||
repeatedField.AddRangeSpan(source); | ||
} | ||
} | ||
} |