| File: src\nuget-client\build\Shared\StringBuilderPool.cs | Web Access |
| Project: src\nuget-client\src\NuGet.Core\NuGet.Common\NuGet.Common.csproj (NuGet.Common) |
// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Text; namespace NuGet { /// <summary> /// Provides a resource pool that enables reusing instances of <see cref="StringBuilder"/> instances. /// </summary> /// <remarks> /// <para> /// Renting and returning buffers with an <see cref="StringBuilderPool"/> can increase performance /// in situations where <see cref="StringBuilder"/> instances are created and destroyed frequently, /// resulting in significant memory pressure on the garbage collector. /// </para> /// <para> /// This class is thread-safe. All members may be used by multiple threads concurrently. /// </para> /// </remarks> internal class StringBuilderPool { private const int MaxPoolSize = 256; private readonly SimplePool<StringBuilder> _pool = new(() => new StringBuilder(MaxPoolSize)); /// <summary> /// Retrieves a shared <see cref="StringBuilderPool"/> instance. /// </summary> public static readonly StringBuilderPool Shared = new(); private StringBuilderPool() { } /// <summary> /// Retrieves a <see cref="StringBuilder"/> that is at least the requested length. /// </summary> /// <param name="minimumCapacity">The minimum capacity of the <see cref="StringBuilder"/> needed.</param> /// <returns> /// A <see cref="StringBuilder"/> that is at least <paramref name="minimumCapacity"/> in length. /// </returns> /// <remarks> /// This buffer is loaned to the caller and should be returned to the same pool via /// <see cref="ToStringAndReturn"/> so that it may be reused in subsequent usage of <see cref="Rent"/>. /// It is not a fatal error to not return a rented string builder, but failure to do so may lead to /// decreased application performance, as the pool may need to create a new instance to replace /// the one lost. /// </remarks> public StringBuilder Rent(int minimumCapacity) { if (minimumCapacity <= MaxPoolSize) { return _pool.Allocate(); } return new StringBuilder(minimumCapacity); } /// <summary> /// Returns to the pool an array that was previously obtained via <see cref="Rent"/> on the same /// <see cref="StringBuilderPool"/> instance, returning the built string. /// </summary> /// <param name="builder"> /// The <see cref="StringBuilder"/> previously obtained from <see cref="Rent"/> to return to the pool. /// </param> /// <remarks> /// Once a <see cref="StringBuilder"/> has been returned to the pool, the caller gives up all ownership /// of the instance and must not use it. The reference returned from a given call to <see cref="Rent"/> /// must only be returned via <see cref="ToStringAndReturn"/> once. The default <see cref="StringBuilderPool"/> /// may hold onto the returned instance in order to rent it again, or it may release the returned instance /// if it's determined that the pool already has enough instances stored. /// </remarks> /// <returns>The string, built from <paramref name="builder"/>.</returns> public string ToStringAndReturn(StringBuilder builder) { string result = builder.ToString(); if (builder.Capacity <= MaxPoolSize) { builder.Clear(); _pool.Free(builder); } return result; } } }