You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by dp...@apache.org on 2017/06/22 20:47:57 UTC

[09/10] logging-log4net git commit: improve performance get_UserName in LoggingEvent.cs

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 <zy...@skbkontur.ru>
Authored: Thu Mar 16 17:09:45 2017 +0500
Committer: Dominik Psenner <dp...@apache.org>
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>