-
Notifications
You must be signed in to change notification settings - Fork 63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reduce heap allocation of the default log message formatting logic in the FileLogger.Log #74
Changes from 1 commit
b50ce1f
42d1435
23838d5
7246743
3afd9b8
7ca803a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
using System; | ||
|
||
#nullable enable | ||
|
||
namespace NReco.Logging.File.Extensions { | ||
public static class DateTimeExtensions { | ||
public static bool TryFormatO(this DateTime dateTime, Span<char> destination, out int charsWritten) { | ||
const int BaseCharCountInFormatO = 27; | ||
|
||
int charsRequired = BaseCharCountInFormatO; | ||
var kind = dateTime.Kind; | ||
var offset = TimeZoneInfo.Local.GetUtcOffset(dateTime); | ||
if (kind == DateTimeKind.Local) { | ||
charsRequired += 6; | ||
} | ||
else if (kind == DateTimeKind.Utc) { | ||
charsRequired++; | ||
} | ||
|
||
if (destination.Length < charsRequired) { | ||
charsWritten = 0; | ||
return false; | ||
} | ||
|
||
charsWritten = charsRequired; | ||
|
||
var year = (uint)dateTime.Year; | ||
var month = (uint)dateTime.Month; | ||
var day = (uint)dateTime.Day; | ||
var hour = (uint)dateTime.Hour; | ||
var minute = (uint)dateTime.Minute; | ||
var second = (uint)dateTime.Second; | ||
var tick = (uint)(dateTime.Ticks - (dateTime.Ticks / TimeSpan.TicksPerSecond * TimeSpan.TicksPerSecond)); | ||
|
||
year.WriteDigits(destination, 4); | ||
destination[4] = '-'; | ||
month.WriteDigits(destination.Slice(5), 2); | ||
destination[7] = '-'; | ||
day.WriteDigits(destination.Slice(8), 2); | ||
destination[10] = 'T'; | ||
hour.WriteDigits(destination.Slice(11), 2); | ||
destination[13] = ':'; | ||
minute.WriteDigits(destination.Slice(14), 2); | ||
destination[16] = ':'; | ||
second.WriteDigits(destination.Slice(17), 2); | ||
destination[19] = '.'; | ||
tick.WriteDigits(destination.Slice(20), 7); | ||
|
||
if (kind == DateTimeKind.Local) { | ||
var offsetTotalMinutes = (int)(offset.Ticks / TimeSpan.TicksPerMinute); | ||
|
||
var sign = '+'; | ||
if (offsetTotalMinutes < 0) { | ||
sign = '-'; | ||
offsetTotalMinutes = -offsetTotalMinutes; | ||
} | ||
|
||
var offsetHours = Math.DivRem(offsetTotalMinutes, 60, out var offsetMinutes); | ||
|
||
destination[27] = sign; | ||
((uint)offsetHours).WriteDigits(destination.Slice(28), 2); | ||
destination[30] = ':'; | ||
((uint)offsetMinutes).WriteDigits(destination.Slice(31), 2); | ||
} | ||
else if (kind == DateTimeKind.Utc) { | ||
destination[27] = 'Z'; | ||
} | ||
|
||
return true; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
using System; | ||
|
||
#nullable enable | ||
|
||
namespace NReco.Logging.File.Extensions { | ||
public static class IntExtensions { | ||
public static int GetFormattedLength(this int value) { | ||
return value == 0 ? 1 : (int)Math.Floor(Math.Log10(Math.Abs((double)value))) + (value > 0 ? 1 : 2); | ||
} | ||
|
||
public static bool TryFormat(this int value, Span<char> destination, out int charsWritten) { | ||
charsWritten = value.GetFormattedLength(); | ||
if (destination.Length < charsWritten) { | ||
charsWritten = 0; | ||
return false; | ||
} | ||
|
||
var dst = destination.Slice(0, charsWritten); | ||
|
||
if (value < 0) { | ||
dst[0] = '-'; | ||
dst = dst.Slice(1); | ||
} | ||
|
||
((uint)Math.Abs((long)value)).WriteDigits(dst, dst.Length); | ||
return true; | ||
} | ||
|
||
internal static void WriteDigits(this uint value, Span<char> destination, int count) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
for (var cur = count - 1; cur > 0; cur--) { | ||
uint temp = '0' + value; | ||
value /= 10; | ||
destination[cur] = (char)(temp - (value * 10)); | ||
} | ||
|
||
destination[0] = (char)('0' + value); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,12 +2,12 @@ | |
|
||
<PropertyGroup> | ||
<Description>Lightweight file logging provider implementation for NET6 / NET8+ / .NET Core without dependencies on logging frameworks. | ||
|
||
How to use: | ||
|
||
using NReco.Logging.File; | ||
|
||
services.AddLogging(loggingBuilder => { | ||
services.AddLogging(loggingBuilder => { | ||
loggingBuilder.AddFile("app.log", append:true); | ||
}); | ||
|
||
|
@@ -19,6 +19,7 @@ More details and examples: https://github.com/nreco/logging | |
<VersionPrefix>1.2.1</VersionPrefix> | ||
<Authors>Vitalii Fedorchenko</Authors> | ||
<TargetFrameworks>netstandard2.0;net6.0;net8.0</TargetFrameworks> | ||
<LangVersion>12.0</LangVersion> | ||
<GenerateDocumentationFile>true</GenerateDocumentationFile> | ||
<AssemblyName>NReco.Logging.File</AssemblyName> | ||
<PackageId>NReco.Logging.File</PackageId> | ||
|
@@ -27,10 +28,10 @@ More details and examples: https://github.com/nreco/logging | |
<PackageProjectUrl>https://github.com/nreco/logging</PackageProjectUrl> | ||
<PackageLicenseUrl>https://raw.githubusercontent.com/nreco/logging/master/LICENSE</PackageLicenseUrl> | ||
<PackageReleaseNotes>How to use: https://github.com/nreco/logging | ||
|
||
Version 1.2.1 changes: | ||
- Added different rolling name conventions #66 (unix-style is supported with 'Descending' convention) | ||
|
||
Version 1.2.0 changes: | ||
- NReco's FileLoggerExtensions should NOT be in the Microsoft.Extensions.Logging namespace #61 | ||
- Added net6 and net8 builds to reference appropriate Microsoft.Logging.Extensions versions | ||
|
@@ -65,7 +66,7 @@ Version 1.1.0 changes: | |
Version 1.0.5 changes: | ||
- log file folder is created automatically if not exists | ||
- environment variables are expanded in the file path | ||
|
||
Version 1.0.4 changes: | ||
- added "File" provider alias for MVC Core 2 filtering rules | ||
- added 'rolling file' behaviour controlled with new FileLoggerProvider properties (FileSizeLimitBytes and MaxRollingFiles)</PackageReleaseNotes> | ||
|
@@ -81,23 +82,11 @@ Version 1.0.4 changes: | |
<SignAssembly>false</SignAssembly> | ||
<AssemblyOriginatorKeyFile>NReco.Logging.File.snk</AssemblyOriginatorKeyFile> | ||
</PropertyGroup> | ||
|
||
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All these packages in their version 8 are compiled for |
||
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.*" /> | ||
<PackageReference Include="Microsoft.Extensions.Logging.Configuration" Version="3.*" /> | ||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.*" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'"> | ||
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.*" /> | ||
<PackageReference Include="Microsoft.Extensions.Logging.Configuration" Version="6.0.*" /> | ||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="6.0.*" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'"> | ||
<ItemGroup> | ||
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.*" /> | ||
<PackageReference Include="Microsoft.Extensions.Logging.Configuration" Version="8.0.*" /> | ||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.*" /> | ||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.*" /> | ||
</ItemGroup> | ||
|
||
</Project> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adapted from https://source.dot.net/#System.Private.CoreLib/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs,24658c862fc77239