-
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
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
b50ce1f
Reduce heap allocation of the default log message formatting logic in…
aannenko 42d1435
Hide TryFormat extensions under preprocessor directives for target fr…
aannenko 23838d5
Add tests for int and DateTime extensions, multi-target the test proj…
aannenko 7246743
Improve DateTimeExtensionsTests a tiny bit
aannenko 3afd9b8
Update .NET Framework target from net462 to net481
aannenko 7ca803a
Restore branching of the nuget packages based on the target framework
aannenko File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
using System; | ||
|
||
#nullable enable | ||
|
||
namespace NReco.Logging.File.Extensions { | ||
public static class DateTimeExtensions { | ||
public static int GetFormattedLength(this DateTime dateTime) { | ||
const int BaseCharCountInFormatO = 27; | ||
|
||
return BaseCharCountInFormatO + dateTime.Kind switch { | ||
DateTimeKind.Local => 6, | ||
DateTimeKind.Utc => 1, | ||
_ => 0 | ||
}; | ||
} | ||
|
||
#if NETSTANDARD2_0 | ||
public static bool TryFormatO(this DateTime dateTime, Span<char> destination, out int charsWritten) { | ||
var charsRequired = dateTime.GetFormattedLength(); | ||
|
||
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); | ||
|
||
var kind = dateTime.Kind; | ||
if (kind == DateTimeKind.Local) { | ||
var offset = TimeZoneInfo.Local.GetUtcOffset(dateTime); | ||
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; | ||
} | ||
#else | ||
public static bool TryFormatO(this DateTime dateTime, Span<char> destination, out int charsWritten) { | ||
return dateTime.TryFormat(destination, out charsWritten, format: "O"); | ||
} | ||
#endif | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
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); | ||
} | ||
|
||
#if NETSTANDARD2_0 | ||
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) { | ||
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); | ||
} | ||
#endif | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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,11 +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.*" /> | ||
<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.*" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'"> | ||
|
@@ -97,7 +98,7 @@ Version 1.0.4 changes: | |
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'"> | ||
<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> |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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/Number.Formatting.cs,566c4d2cd4ba9487