diff options
author | Mike Krüger <mikkrg@microsoft.com> | 2018-02-22 18:58:46 +0300 |
---|---|---|
committer | Mike Krüger <mikkrg@microsoft.com> | 2018-02-22 18:58:46 +0300 |
commit | 53b566cb7d54703faaa1c160c270abdf9a3f3cf3 (patch) | |
tree | e0d6284fda385c14db6f2c6237e8dc2260c60a0a /main/src | |
parent | f9a21f193342bf0679d8a72abbf62008fe527bdf (diff) |
[Core] Implemented string builder pooling.
Diffstat (limited to 'main/src')
7 files changed, 450 insertions, 7 deletions
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.CodeGeneration/AbstractGenerateAction.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.CodeGeneration/AbstractGenerateAction.cs index c51a585252..8a7609ab5a 100644 --- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.CodeGeneration/AbstractGenerateAction.cs +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.CodeGeneration/AbstractGenerateAction.cs @@ -38,6 +38,8 @@ using MonoDevelop.Ide.Editor; using MonoDevelop.Core.Text; using MonoDevelop.CSharp.Completion; using MonoDevelop.CSharp.Formatting; +using Microsoft.CodeAnalysis.Formatting; +using MonoDevelop.Core; namespace MonoDevelop.CodeGeneration { @@ -119,7 +121,7 @@ namespace MonoDevelop.CodeGeneration static string AddIndent (string text, string indent) { var doc = TextEditorFactory.CreateNewReadonlyDocument (new StringTextSource (text), ""); - var result = new StringBuilder (); + var result = StringBuilderCache.New (); foreach (var line in doc.GetLines ()) { result.Append (indent); result.Append (doc.GetTextAt (line.SegmentIncludingDelimiter)); @@ -143,7 +145,7 @@ namespace MonoDevelop.CodeGeneration includedMembers.Add (store.GetValue (iter, 3)); } } - var output = new StringBuilder (); + var output = StringBuilderCache.New (); string indent = options.Editor.GetVirtualIndentationString (options.Editor.CaretLine); foreach (string nodeText in GenerateCode (includedMembers)) { if (output.Length > 0) { diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Logging/AssertLoggingTraceListener.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Logging/AssertLoggingTraceListener.cs index 9cf02b44e3..f9f8bf53c7 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Logging/AssertLoggingTraceListener.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Logging/AssertLoggingTraceListener.cs @@ -45,7 +45,7 @@ namespace MonoDevelop.Core.Logging if (callerFrame == frames.Length - 1) callerFrame = 0; - var sb = new StringBuilder (); + var sb = StringBuilderCache.New(); if (IsRealMessage (message)) { if (!string.IsNullOrEmpty (detailMessage)) { sb.AppendFormat ("Failed assertion: {0} - {1}", message, detailMessage); diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj index 9fdd2d303a..108da5d396 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj @@ -756,6 +756,7 @@ <Compile Include="MonoDevelop.FSW\OSX\SR.cs" /> <Compile Include="MonoDevelop.FSW\FileSystemWatcher.cs" /> <Compile Include="MonoDevelop.FSW\Mono\FileSystemWatcher.cs" /> + <Compile Include="MonoDevelop.Core\StringBuilderCache.cs" /> </ItemGroup> <ItemGroup> <None Include="Makefile.am" /> @@ -800,7 +801,7 @@ <InternalsVisibleTo Include="MonoDevelop.Ide.Tests" /> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> - <Target Name="BeforeBuild" Inputs="BuildVariables.cs.in; $(MSBuildProjectDirectory)\..\..\..\..\version.config" Outputs="BuildVariables.cs" Condition="Exists('$(MSBuildProjectDirectory)\..\..\..\..\version.config')" > + <Target Name="BeforeBuild" Inputs="BuildVariables.cs.in; $(MSBuildProjectDirectory)\..\..\..\..\version.config" Outputs="BuildVariables.cs" Condition="Exists('$(MSBuildProjectDirectory)\..\..\..\..\version.config')"> <MakeDir Directories="$(FullBuildInfo)" /> <Csc Sources="$(ConfigureScript)" OutputAssembly="$(ConfigureScriptExe)" ToolExe="$(CscToolExe)" ToolPath="$(CscToolPath)" Condition="!Exists('$(ConfigureScriptExe)')" /> <Exec Command="$(MonoLauncher)$(ConfigureScriptExe) gen-buildinfo $(FullBuildInfo)" WorkingDirectory="$(MSBuildProjectDirectory)" /> diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/StringBuilderCache.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/StringBuilderCache.cs new file mode 100644 index 0000000000..a184724f47 --- /dev/null +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/StringBuilderCache.cs @@ -0,0 +1,439 @@ +// +// StringBuilderCache.cs +// +// Author: +// Mike Krüger <mikkrg@microsoft.com> +// +// Copyright (c) 2018 Microsoft Corporation. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Diagnostics; +using System.Text; +using System.Threading; +using System.Collections.Immutable; +using System.Security.Cryptography; + +namespace MonoDevelop.Core +{ + /// <summary> + /// This is a pool for storing StringBuilder objects. + /// </summary> + public static class StringBuilderCache + { + static ImmutableQueue<CachedStringBuilder> pool = ImmutableQueue<CachedStringBuilder>.Empty; + + public static CachedStringBuilder New () + { + pool = pool.Dequeue (out CachedStringBuilder result); + if (result != null) { + result.Cached = false; + return result; + } + return new CachedStringBuilder (); + } + + internal static void Put (CachedStringBuilder sb) + { + sb.Clear (); + sb.Cached = true; + pool = pool.Enqueue (sb); + } + } + + /// <summary> + /// A string builder which puts itself into the object pool on a ToString() call. + /// </summary> + public class CachedStringBuilder + { + readonly StringBuilder sb = new StringBuilder (); + + internal bool Cached { get; set; } + + public int Capacity { get => sb.Capacity; set => sb.Capacity = value; } + public int Length { get => sb.Length; set => sb.Length = value; } + + public int MaxCapacity { get => sb.MaxCapacity; } + + public char this [int index] { get => sb [index]; set => sb [index] = value; } + + public CachedStringBuilder Append (long value) + { + sb.Append (value); + return this; + } + + public CachedStringBuilder Append (ulong value) + { + sb.Append (value); + return this; + } + + public CachedStringBuilder Append (uint value) + { + sb.Append (value); + return this; + } + + public CachedStringBuilder Append (ushort value) + { + sb.Append (value); + return this; + } + + public CachedStringBuilder Append (string value, int startIndex, int count) + { + sb.Append (value, startIndex, count); + return this; + } + + public CachedStringBuilder Append (string value) + { + sb.Append (value); + return this; + } + + public CachedStringBuilder Append (float value) + { + sb.Append (value); + return this; + } + + public CachedStringBuilder Append (sbyte value) + { + sb.Append (value); + return this; + } + + public CachedStringBuilder Append (object value) + { + sb.Append (value); + return this; + } + + public CachedStringBuilder Append (int value) + { + sb.Append (value); + return this; + } + + public CachedStringBuilder Append (char [] value, int startIndex, int charCount) + { + sb.Append (value, startIndex, charCount); + return this; + } + + public CachedStringBuilder Append (double value) + { + sb.Append (value); + return this; + } + + public CachedStringBuilder Append (decimal value) + { + sb.Append (value); + return this; + } + + public CachedStringBuilder Append (char [] value) + { + sb.Append (value); + return this; + } + + public CachedStringBuilder Append (char value, int repeatCount) + { + sb.Append (value, repeatCount); + return this; + } + + public unsafe CachedStringBuilder Append (char* value, int valueCount) + { + sb.Append (value, valueCount); + return this; + } + + public CachedStringBuilder Append (char value) + { + sb.Append (value); + return this; + } + + public CachedStringBuilder Append (byte value) + { + sb.Append (value); + return this; + } + + public CachedStringBuilder Append (bool value) + { + sb.Append (value); + return this; + } + + public CachedStringBuilder Append (short value) + { + sb.Append (value); + return this; + } + + public CachedStringBuilder AppendFormat (string format, object arg0, object arg1, object arg2) + { + sb.AppendFormat (format, arg0, arg1, arg2); + return this; + } + + public CachedStringBuilder AppendFormat (string format, params object [] args) + { + sb.AppendFormat (format, args); + return this; + } + + public CachedStringBuilder AppendFormat (string format, object arg0, object arg1) + { + sb.AppendFormat (format, arg0, arg1); + return this; + } + + public CachedStringBuilder AppendFormat (string format, object arg0) + { + sb.AppendFormat (format, arg0); + return this; + } + + public CachedStringBuilder AppendFormat (IFormatProvider provider, string format, object arg0, object arg1, object arg2) + { + sb.AppendFormat (provider, format, arg0, arg1, arg2); + return this; + } + + public CachedStringBuilder AppendFormat (IFormatProvider provider, string format, object arg0, object arg1) + { + sb.AppendFormat (provider, format, arg0, arg1); + return this; + } + + public CachedStringBuilder AppendFormat (IFormatProvider provider, string format, object arg0) + { + sb.AppendFormat (provider, format, arg0); + return this; + } + + public CachedStringBuilder AppendFormat (IFormatProvider provider, string format, params object [] args) + { + sb.AppendFormat (provider, format, args); + return this; + } + + public CachedStringBuilder AppendLine () + { + sb.AppendLine (); + return this; + } + + public CachedStringBuilder AppendLine (string value) + { + sb.AppendLine (value); + return this; + } + + public CachedStringBuilder Clear () + { + sb.Clear (); + return this; + } + + public void CopyTo (int sourceIndex, char [] destination, int destinationIndex, int count) + { + sb.CopyTo (sourceIndex, destination, destinationIndex, count); + } + + public int EnsureCapacity (int capacity) + { + return sb.EnsureCapacity(capacity); + } + + public bool Equals (StringBuilder sb) + { + return this.sb.Equals (sb); + } + + public bool Equals (CachedStringBuilder csb) + { + return this.sb.Equals (csb.sb); + } + + public CachedStringBuilder Insert (int index, uint value) + { + sb.Insert (index, value); + return this; + } + + public CachedStringBuilder Insert (int index, ushort value) + { + sb.Insert (index, value); + return this; + } + + public CachedStringBuilder Insert (int index, string value, int count) + { + sb.Insert (index, value, count); + return this; + } + + public CachedStringBuilder Insert (int index, string value) + { + sb.Insert (index, value); + return this; + } + + public CachedStringBuilder Insert (int index, float value) + { + sb.Insert (index, value); + return this; + } + + public CachedStringBuilder Insert (int index, sbyte value) + { + sb.Insert (index, value); + return this; + } + + public CachedStringBuilder Insert (int index, ulong value) + { + sb.Insert (index, value); + return this; + } + + public CachedStringBuilder Insert (int index, object value) + { + sb.Insert (index, value); + return this; + } + + public CachedStringBuilder Insert (int index, double value) + { + sb.Insert (index, value); + return this; + } + + public CachedStringBuilder Insert (int index, int value) + { + sb.Insert (index, value); + return this; + } + + public CachedStringBuilder Insert (int index, decimal value) + { + sb.Insert (index, value); + return this; + } + + public CachedStringBuilder Insert (int index, char [] value, int startIndex, int charCount) + { + sb.Insert (index, value, startIndex, charCount); + return this; + } + + public CachedStringBuilder Insert (int index, char [] value) + { + sb.Insert (index, value); + return this; + } + + public CachedStringBuilder Insert (int index, char value) + { + sb.Insert (index, value); + return this; + } + + public CachedStringBuilder Insert (int index, byte value) + { + sb.Insert (index, value); + return this; + } + + public CachedStringBuilder Insert (int index, bool value) + { + sb.Insert (index, value); + return this; + } + + public CachedStringBuilder Insert (int index, long value) + { + sb.Insert (index, value); + return this; + } + + public CachedStringBuilder Insert (int index, short value) + { + sb.Insert (index, value); + return this; + } + + public CachedStringBuilder Remove (int startIndex, int length) + { + sb.Remove (startIndex, length); + return this; + } + + public CachedStringBuilder Replace (string oldValue, string newValue, int startIndex, int count) + { + sb.Replace (oldValue, newValue, startIndex, count); + return this; + } + + public CachedStringBuilder Replace (char oldChar, char newChar) + { + sb.Replace (oldChar, newChar); + return this; + } + + public CachedStringBuilder Replace (char oldChar, char newChar, int startIndex, int count) + { + sb.Replace (oldChar, newChar, startIndex, count); + return this; + } + + public CachedStringBuilder Replace (string oldValue, string newValue) + { + sb.Replace (oldValue, newValue); + return this; + } + + public override string ToString () + { + if (Cached) + throw new InvalidOperationException ("Object is cached."); + var result = sb.ToString (); + StringBuilderCache.Put (this); + return result; + } + + public string ToString (int startIndex, int length) + { + if (Cached) + throw new InvalidOperationException ("Object is cached."); + var result = sb.ToString (startIndex, length); + StringBuilderCache.Put (this); + return result; + } + } +}
\ No newline at end of file diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchResult.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchResult.cs index c44cd39d56..3da90ec0c1 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchResult.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchResult.cs @@ -106,7 +106,7 @@ namespace MonoDevelop.Components.MainToolbar { var lane = StringMatcher.GetMatcher (toMatch, true).GetMatch (text);
var matchHexColor = selected ? selectedResultMatchTextColor : resultMatchTextColor; - StringBuilder result = new StringBuilder (text.Length + matchHexColor.Length + 46); + var result = StringBuilderCache.New (); if (lane != null) { int lastPos = 0; for (int n=0; n < lane.Length; n++) { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/Ambience.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/Ambience.cs index 9b25d238c1..b48f83becd 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/Ambience.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/Ambience.cs @@ -106,7 +106,7 @@ namespace MonoDevelop.Ide.TypeSystem if (String.IsNullOrEmpty (str)) return string.Empty; - StringBuilder sb = new StringBuilder (str.Length); + var sb = StringBuilderCache.New (); MarkupUtilities.AppendEscapedString (sb, str, 0, str.Length); return sb.ToString (); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MarkupUtilities.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MarkupUtilities.cs index 00fee4d6f3..5331637730 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MarkupUtilities.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MarkupUtilities.cs @@ -28,6 +28,7 @@ using System; using System.Text; +using MonoDevelop.Core; namespace MonoDevelop.Ide.TypeSystem { @@ -39,7 +40,7 @@ namespace MonoDevelop.Ide.TypeSystem static string EscapedApostrophe = "'"; static string EscapedQuote = """; - public static void AppendEscapedString (StringBuilder builder, string toEscape, int start, int count) + public static void AppendEscapedString (CachedStringBuilder builder, string toEscape, int start, int count) { if (toEscape == null) return; |