StringBuilderCache.cs 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. // See the LICENSE file in the project root for more information.
  4. namespace System.Text
  5. {
  6. /// <summary>Provide a cached reusable instance of stringbuilder per thread.</summary>
  7. internal static class StringBuilderCache
  8. {
  9. // The value 360 was chosen in discussion with performance experts as a compromise between using
  10. // as litle memory per thread as possible and still covering a large part of short-lived
  11. // StringBuilder creations on the startup path of VS designers.
  12. private const int MaxBuilderSize = 360;
  13. private const int DefaultCapacity = 16; // == StringBuilder.DefaultCapacity
  14. // WARNING: We allow diagnostic tools to directly inspect this member (t_cachedInstance).
  15. // See https://github.com/dotnet/corert/blob/master/Documentation/design-docs/diagnostics/diagnostics-tools-contract.md for more details.
  16. // Please do not change the type, the name, or the semantic usage of this member without understanding the implication for tools.
  17. // Get in touch with the diagnostics team if you have questions.
  18. [ThreadStatic]
  19. private static StringBuilder t_cachedInstance;
  20. /// <summary>Get a StringBuilder for the specified capacity.</summary>
  21. /// <remarks>If a StringBuilder of an appropriate size is cached, it will be returned and the cache emptied.</remarks>
  22. public static StringBuilder Acquire(int capacity = DefaultCapacity)
  23. {
  24. if (capacity <= MaxBuilderSize)
  25. {
  26. StringBuilder sb = t_cachedInstance;
  27. if (sb != null)
  28. {
  29. // Avoid stringbuilder block fragmentation by getting a new StringBuilder
  30. // when the requested size is larger than the current capacity
  31. if (capacity <= sb.Capacity)
  32. {
  33. t_cachedInstance = null;
  34. sb.Clear();
  35. return sb;
  36. }
  37. }
  38. }
  39. return new StringBuilder(capacity);
  40. }
  41. /// <summary>Place the specified builder in the cache if it is not too big.</summary>
  42. public static void Release(StringBuilder sb)
  43. {
  44. if (sb.Capacity <= MaxBuilderSize)
  45. {
  46. t_cachedInstance = sb;
  47. }
  48. }
  49. /// <summary>ToString() the stringbuilder, Release it to the cache, and return the resulting string.</summary>
  50. public static string GetStringAndRelease(StringBuilder sb)
  51. {
  52. string result = sb.ToString();
  53. Release(sb);
  54. return result;
  55. }
  56. }
  57. }