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>

Reply via email to