Skip to content

Commit

Permalink
ThreadIdLayoutRenderer - StringBuilder Append without garbage
Browse files Browse the repository at this point in the history
  • Loading branch information
snakefoot committed Oct 9, 2016
1 parent 4e63930 commit 182c9dd
Show file tree
Hide file tree
Showing 11 changed files with 160 additions and 7 deletions.
64 changes: 64 additions & 0 deletions src/NLog/Internal/StringBuilderExt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,69 @@ public static void Append(this StringBuilder builder, object o, LogEventInfo log
builder.Append(Convert.ToString(o, formatProvider));
}

/// <summary>
/// Appends int without using culture, and most importantly without garbage
/// </summary>
/// <param name="builder"></param>
/// <param name="value">value to append</param>
public static void AppendInvariant(this StringBuilder builder, int value)
{
// Deal with negative numbers
if (value < 0)
{
builder.Append('-');
uint uint_value = uint.MaxValue - ((uint)value) + 1; //< This is to deal with Int32.MinValue
AppendInvariant(builder, uint_value);
}
else
{
AppendInvariant(builder, (uint)value);
}
}

/// <summary>
/// Appends uint without using culture, and most importantly without garbage
///
/// Credits Gavin Pugh - http://www.gavpugh.com/2010/04/01/xnac-avoiding-garbage-when-working-with-stringbuilder/
/// </summary>
/// <param name="builder"></param>
/// <param name="value">value to append</param>
public static void AppendInvariant(this StringBuilder builder, uint value)
{
if (value == 0)
{
builder.Append('0');
return;
}

// Calculate length of integer when written out
int length = 0;
uint length_calc = value;

do
{
length_calc /= 10;
length++;
}
while (length_calc > 0);

// Pad out space for writing.
builder.Append('0', length);

int strpos = builder.Length;

// We're writing backwards, one character at a time.
while (length > 0)
{
strpos--;

// Lookup from static char array, to cover hex values too
builder[strpos] = charToInt[value % 10];

value /= 10;
length--;
}
}
private static readonly char[] charToInt = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
}
}
2 changes: 1 addition & 1 deletion src/NLog/LayoutRenderers/CounterLayoutRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ protected override void Append(StringBuilder builder, LogEventInfo logEvent)
this.Value += this.Increment;
}

builder.Append(v.ToString(CultureInfo.InvariantCulture));
Internal.StringBuilderExt.AppendInvariant(builder, v);
}

private static int GetNextSequenceValue(string sequenceName, int defaultValue, int increment)
Expand Down
3 changes: 1 addition & 2 deletions src/NLog/LayoutRenderers/ProcessIdLayoutRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@

namespace NLog.LayoutRenderers
{
using System.Globalization;
using System.Text;
using NLog.Config;
using NLog.Internal;
Expand All @@ -55,7 +54,7 @@ public class ProcessIdLayoutRenderer : LayoutRenderer
/// <param name="logEvent">Logging event.</param>
protected override void Append(StringBuilder builder, LogEventInfo logEvent)
{
builder.Append(ThreadIDHelper.Instance.CurrentProcessID.ToString(CultureInfo.InvariantCulture));
builder.AppendInvariant(ThreadIDHelper.Instance.CurrentProcessID);
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/NLog/LayoutRenderers/ThreadIdLayoutRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@

namespace NLog.LayoutRenderers
{
using System.Globalization;
using System.Text;
using System.Threading;

Expand All @@ -51,7 +50,7 @@ public class ThreadIdLayoutRenderer : LayoutRenderer
protected override void Append(StringBuilder builder, LogEventInfo logEvent)
{
//no culture needed for ints
builder.Append(Thread.CurrentThread.ManagedThreadId.ToString(CultureInfo.InvariantCulture));
Internal.StringBuilderExt.AppendInvariant(builder, Thread.CurrentThread.ManagedThreadId);
}
}
}
83 changes: 83 additions & 0 deletions tests/NLog.UnitTests/Internal/StringBuilderExtTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
//
// Copyright (c) 2004-2016 Jaroslaw Kowalski <jaak@jkowalski.net>, Kim Christensen, Julian Verdurmen
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * Neither the name of Jaroslaw Kowalski nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.
//

#if !SILVERLIGHT
//no silverlight for xunit InlineData

using System.Text;
using NLog.Internal;
using Xunit;
using Xunit.Extensions;

namespace NLog.UnitTests.Internal
{
public class StringBuilderExtTests : NLogTestBase
{
[Theory]
[InlineData(0)]
[InlineData(1)]
[InlineData(2)]
[InlineData(3)]
[InlineData(4)]
[InlineData(5)]
[InlineData(6)]
[InlineData(7)]
[InlineData(8)]
[InlineData(9)]
[InlineData(10)]
[InlineData(12)]
[InlineData(123)]
[InlineData(1234)]
[InlineData(12345)]
[InlineData(123456)]
[InlineData(1234567)]
[InlineData(12345678)]
[InlineData(123456789)]
[InlineData(1234567890)]
[InlineData(int.MaxValue)]
[InlineData(int.MinValue)]
void TestAppendInvariant(int input)
{
StringBuilder sb = new StringBuilder();
StringBuilderExt.AppendInvariant(sb, input);
Assert.Equal(input.ToString(System.Globalization.CultureInfo.InvariantCulture), sb.ToString());

input = 0 - input;
sb.Clear();
StringBuilderExt.AppendInvariant(sb, input);
Assert.Equal(input.ToString(System.Globalization.CultureInfo.InvariantCulture), sb.ToString());
}
}
}

#endif
1 change: 1 addition & 0 deletions tests/NLog.UnitTests/NLog.UnitTests.mono.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
<Compile Include="Internal\FilePathLayoutTests.cs" />
<Compile Include="Internal\NetworkSenders\TcpNetworkSenderTests.cs" />
<Compile Include="Internal\NetworkSenders\UdpNetworkSenderTests.cs" />
<Compile Include="Internal\StringBuilderExtTests.cs" />
<Compile Include="Internal\StringHelpersTests.cs" />
<Compile Include="Internal\UrlHelperTests.cs" />
<Compile Include="LayoutRenderers\AppDomainLayoutRendererTests.cs" />
Expand Down
1 change: 1 addition & 0 deletions tests/NLog.UnitTests/NLog.UnitTests.netfx35.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@
<Compile Include="Internal\FilePathLayoutTests.cs" />
<Compile Include="Internal\NetworkSenders\TcpNetworkSenderTests.cs" />
<Compile Include="Internal\NetworkSenders\UdpNetworkSenderTests.cs" />
<Compile Include="Internal\StringBuilderExtTests.cs" />
<Compile Include="Internal\StringHelpersTests.cs" />
<Compile Include="Internal\UrlHelperTests.cs" />
<Compile Include="LayoutRenderers\AppDomainLayoutRendererTests.cs" />
Expand Down
1 change: 1 addition & 0 deletions tests/NLog.UnitTests/NLog.UnitTests.netfx40.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@
<Compile Include="Internal\FilePathLayoutTests.cs" />
<Compile Include="Internal\NetworkSenders\TcpNetworkSenderTests.cs" />
<Compile Include="Internal\NetworkSenders\UdpNetworkSenderTests.cs" />
<Compile Include="Internal\StringBuilderExtTests.cs" />
<Compile Include="Internal\StringHelpersTests.cs" />
<Compile Include="Internal\UrlHelperTests.cs" />
<Compile Include="LayoutRenderers\AppDomainLayoutRendererTests.cs" />
Expand Down
7 changes: 5 additions & 2 deletions tests/NLog.UnitTests/NLog.UnitTests.netfx45.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<ApplicationIcon></ApplicationIcon>
<AssemblyKeyContainerName></AssemblyKeyContainerName>
<ApplicationIcon>
</ApplicationIcon>
<AssemblyKeyContainerName>
</AssemblyKeyContainerName>
<AssemblyName>NLog.UnitTests</AssemblyName>
<AssemblyOriginatorKeyFile>NLogTests.snk</AssemblyOriginatorKeyFile>
<DelaySign>false</DelaySign>
Expand Down Expand Up @@ -161,6 +163,7 @@
<Compile Include="Internal\FilePathLayoutTests.cs" />
<Compile Include="Internal\NetworkSenders\TcpNetworkSenderTests.cs" />
<Compile Include="Internal\NetworkSenders\UdpNetworkSenderTests.cs" />
<Compile Include="Internal\StringBuilderExtTests.cs" />
<Compile Include="Internal\StringHelpersTests.cs" />
<Compile Include="Internal\UrlHelperTests.cs" />
<Compile Include="LayoutRenderers\AppDomainLayoutRendererTests.cs" />
Expand Down
1 change: 1 addition & 0 deletions tests/NLog.UnitTests/NLog.UnitTests.sl4.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@
<Compile Include="Internal\FilePathLayoutTests.cs" />
<Compile Include="Internal\NetworkSenders\TcpNetworkSenderTests.cs" />
<Compile Include="Internal\NetworkSenders\UdpNetworkSenderTests.cs" />
<Compile Include="Internal\StringBuilderExtTests.cs" />
<Compile Include="Internal\StringHelpersTests.cs" />
<Compile Include="Internal\UrlHelperTests.cs" />
<Compile Include="LayoutRenderers\AppDomainLayoutRendererTests.cs" />
Expand Down
1 change: 1 addition & 0 deletions tests/NLog.UnitTests/NLog.UnitTests.sl5.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@
<Compile Include="Internal\FilePathLayoutTests.cs" />
<Compile Include="Internal\NetworkSenders\TcpNetworkSenderTests.cs" />
<Compile Include="Internal\NetworkSenders\UdpNetworkSenderTests.cs" />
<Compile Include="Internal\StringBuilderExtTests.cs" />
<Compile Include="Internal\StringHelpersTests.cs" />
<Compile Include="Internal\UrlHelperTests.cs" />
<Compile Include="LayoutRenderers\AppDomainLayoutRendererTests.cs" />
Expand Down

0 comments on commit 182c9dd

Please sign in to comment.