improve performance get_UserName in LoggingEvent.cs
Project: http://git-wip-us.apache.org/repos/asf/logging-log4net/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4net/commit/8a82ed76 Tree: http://git-wip-us.apache.org/repos/asf/logging-log4net/tree/8a82ed76 Diff: http://git-wip-us.apache.org/repos/asf/logging-log4net/diff/8a82ed76 Branch: refs/heads/pr/old/45 Commit: 8a82ed76474c48343eda7f769e1989f43ce42f7e Parents: 87e8a49 Author: zyrainovdv <[email protected]> Authored: Thu Mar 16 17:09:45 2017 +0500 Committer: Dominik Psenner <[email protected]> Committed: Thu Jun 22 22:42:32 2017 +0200 ---------------------------------------------------------------------- src/Core/LoggingEvent.cs | 53 +------------ src/Core/WindowsIdentityProvider.cs | 123 +++++++++++++++++++++++++++++++ src/log4net.vs2008.csproj | 1 + src/log4net.vs2010.csproj | 1 + src/log4net.vs2012.csproj | 1 + 5 files changed, 128 insertions(+), 51 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/8a82ed76/src/Core/LoggingEvent.cs ---------------------------------------------------------------------- diff --git a/src/Core/LoggingEvent.cs b/src/Core/LoggingEvent.cs index eb54a60..751d521 100644 --- a/src/Core/LoggingEvent.cs +++ b/src/Core/LoggingEvent.cs @@ -22,9 +22,6 @@ using System.Collections; using System.IO; #if (!NETCF) using System.Runtime.Serialization; -#if !NETSTANDARD1_3 -using System.Security.Principal; -#endif #endif using log4net.Util; @@ -852,45 +849,6 @@ namespace log4net.Core /// underlying runtime has no support for retrieving the name of the /// current user. /// </value> - /// <remarks> - /// <para> - /// Calls <c>WindowsIdentity.GetCurrent().Name</c> to get the name of - /// the current windows user. - /// </para> - /// <para> - /// To improve performance, we could cache the string representation of - /// the name, and reuse that as long as the identity stayed constant. - /// Once the identity changed, we would need to re-assign and re-render - /// the string. - /// </para> - /// <para> - /// However, the <c>WindowsIdentity.GetCurrent()</c> call seems to - /// return different objects every time, so the current implementation - /// doesn't do this type of caching. - /// </para> - /// <para> - /// Timing for these operations: - /// </para> - /// <list type="table"> - /// <listheader> - /// <term>Method</term> - /// <description>Results</description> - /// </listheader> - /// <item> - /// <term><c>WindowsIdentity.GetCurrent()</c></term> - /// <description>10000 loops, 00:00:00.2031250 seconds</description> - /// </item> - /// <item> - /// <term><c>WindowsIdentity.GetCurrent().Name</c></term> - /// <description>10000 loops, 00:00:08.0468750 seconds</description> - /// </item> - /// </list> - /// <para> - /// This means we could speed things up almost 40 times by caching the - /// value of the <c>WindowsIdentity.GetCurrent().Name</c> property, since - /// this takes (8.04-0.20) = 7.84375 seconds. - /// </para> - /// </remarks> public string UserName { get @@ -903,15 +861,8 @@ namespace log4net.Core #else try { - WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent(); - if (windowsIdentity != null && windowsIdentity.Name != null) - { - m_data.UserName = windowsIdentity.Name; - } - else - { - m_data.UserName = ""; - } + var currentIdentityName = WindowsIdentityProvider.CurrentIdentityName; + m_data.UserName = currentIdentityName ?? ""; } catch(System.Security.SecurityException) { http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/8a82ed76/src/Core/WindowsIdentityProvider.cs ---------------------------------------------------------------------- diff --git a/src/Core/WindowsIdentityProvider.cs b/src/Core/WindowsIdentityProvider.cs new file mode 100644 index 0000000..9f6427d --- /dev/null +++ b/src/Core/WindowsIdentityProvider.cs @@ -0,0 +1,123 @@ +using System; +using System.Security; +using System.Security.Principal; +using System.Threading; +using log4net.Util; + +namespace log4net.Core +{ + /// <summary> + /// Provide methods for interactions with WindowsIdentity. + /// </summary> + public class WindowsIdentityProvider + { + private readonly static Type declaringType = typeof(WindowsIdentityProvider); + + #region Public Static Properties + + /// <summary> + /// Gets the cached name of the current WindowsIdentity. + /// </summary> + /// <value> + /// The cached name of the current WindowsIdentity. + /// </value> + /// <exception cref="SecurityException"/> + /// <remarks> + /// <para> + /// Gets the cached name of the current WindowsIdentity. + /// </para> + /// <para> + /// Calls <c>WindowsIdentity.GetCurrent().Name</c> to get the name of + /// the current windows user and cache it. + /// </para> + /// </remarks> + public static string CurrentIdentityName + { + get + { + if (s_currentIdentityName != null) + return s_currentIdentityName; + lock (s_syncRoot) + { + if (s_currentIdentityName != null) + return s_currentIdentityName; + s_currentIdentityName = GetCurrentIdentityName(); + s_updateCurrentIdentityNameTimer = new Timer(UpdateCurrentIdentityName, null, s_updateCurrentIdentityNameInterval, s_updateCurrentIdentityNameInterval); + } + return s_currentIdentityName; + } + } + + private static void UpdateCurrentIdentityName(object state) + { + try + { + var identityName = GetCurrentIdentityName(); + if (!string.IsNullOrEmpty(identityName)) + { + s_currentIdentityName = identityName; + } + } + catch (SecurityException) + { + // This security exception will occur if the caller does not have + // some undefined set of SecurityPermission flags. + LogLog.Debug(declaringType, "Security exception while trying to get current windows identity. Error Ignored. Empty user name."); + } + } + + /// <para> + /// Timing for these operations: + /// </para> + /// <list type="table"> + /// <listheader> + /// <term>Method</term> + /// <description>Results</description> + /// </listheader> + /// <item> + /// <term><c>WindowsIdentity.GetCurrent()</c></term> + /// <description>10000 loops, 00:00:00.2031250 seconds</description> + /// </item> + /// <item> + /// <term><c>WindowsIdentity.GetCurrent().Name</c></term> + /// <description>10000 loops, 00:00:08.0468750 seconds</description> + /// </item> + /// </list> + /// <para> + /// This means we could speed things up almost 40 times by caching the + /// value of the <c>WindowsIdentity.GetCurrent().Name</c> property, since + /// this takes (8.04-0.20) = 7.84375 seconds. + /// </para> + private static string GetCurrentIdentityName() + { + WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent(); + return windowsIdentity.Name ?? ""; + } + + #endregion + + #region Private Static Fields + + /// <summary> + /// Lock object used to synchronize updates within this instance. + /// </summary> + private readonly static object s_syncRoot = new object(); + + /// <summary> + /// Interval for current Identity Name updates. + /// </summary> + private readonly static TimeSpan s_updateCurrentIdentityNameInterval = TimeSpan.FromSeconds(1); + + /// <summary> + /// Timer for current Identity Name updates. + /// </summary> + private static Timer s_updateCurrentIdentityNameTimer; + + /// <value> + /// The cached name of the current WindowsIdentity. + /// </value> + private static volatile string s_currentIdentityName; + + #endregion + } +} http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/8a82ed76/src/log4net.vs2008.csproj ---------------------------------------------------------------------- diff --git a/src/log4net.vs2008.csproj b/src/log4net.vs2008.csproj index 1166930..1500778 100644 --- a/src/log4net.vs2008.csproj +++ b/src/log4net.vs2008.csproj @@ -317,6 +317,7 @@ <SubType>Code</SubType> </Compile> <Compile Include="Core\TimeEvaluator.cs" /> + <Compile Include="Core\WindowsIdentityProvider.cs" /> <Compile Include="Core\WrapperMap.cs"> <SubType>Code</SubType> </Compile> http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/8a82ed76/src/log4net.vs2010.csproj ---------------------------------------------------------------------- diff --git a/src/log4net.vs2010.csproj b/src/log4net.vs2010.csproj index 7865f1e..5661830 100644 --- a/src/log4net.vs2010.csproj +++ b/src/log4net.vs2010.csproj @@ -333,6 +333,7 @@ <SubType>Code</SubType> </Compile> <Compile Include="Core\TimeEvaluator.cs" /> + <Compile Include="Core\WindowsIdentityProvider.cs" /> <Compile Include="Core\WrapperMap.cs"> <SubType>Code</SubType> </Compile> http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/8a82ed76/src/log4net.vs2012.csproj ---------------------------------------------------------------------- diff --git a/src/log4net.vs2012.csproj b/src/log4net.vs2012.csproj index 05a7062..b221434 100644 --- a/src/log4net.vs2012.csproj +++ b/src/log4net.vs2012.csproj @@ -333,6 +333,7 @@ <SubType>Code</SubType> </Compile> <Compile Include="Core\TimeEvaluator.cs" /> + <Compile Include="Core\WindowsIdentityProvider.cs" /> <Compile Include="Core\WrapperMap.cs"> <SubType>Code</SubType> </Compile>
