FreeAndNil opened a new pull request, #304:
URL: https://github.com/apache/logging-log4net/pull/304

   The cache added in 2.0.15 (commit 9305ea9b) was declared as an instance field
   on `LoggingEvent`. Since every event is a fresh instance the guard was always
   false, so the `??=` never hit and each event ran a full
   `WindowsIdentity.GetCurrent().Name` - measured at 79.6 us on the machine used
   here. The same commit had changed `TryGetCurrentUserName` from static to
   instance, so the caching it introduced has never taken effect.
   
   The doc comment above the property already described the intended design and
   the reason it was abandoned: the name should be cached "as long as the 
identity
   stayed constant", but `WindowsIdentity.GetCurrent()` "seems to return 
different
   objects every time". Object identity was the wrong comparison. The security
   identifier is stable, and obtaining the identity is far cheaper than 
resolving
   its name - the timing table in that same comment puts the two at roughly 20 
ns
   against 804 ns.
   
   So the name is now cached without changing what the property reports:
   
   - A thread that is not impersonating runs as the process identity, so its 
name
     is resolved once per process. `WindowsIdentity.GetCurrent(ifImpersonating:
     true)` answers that question for 249 ns against 78 us for a name, making 
this
     the fast path for services, console applications and ASP.NET Core.
   - A thread that is impersonating - classic ASP.NET with
     `<identity impersonate="true"/>`, or `RunImpersonated` - has its name
     resolved once per distinct user, keyed by security identifier and capped at
     `MaxCachedUserNames` entries so that a site in front of a large directory
     cannot accumulate one entry per visitor.
   
   The process-identity value is assigned in exactly one place, inside the 
branch
   that has already established the thread is not impersonating. Seeding it from
   an impersonating thread would report that user for the rest of the process,
   which `ImpersonationDoesNotSeedTheProcessUserName` guards against.
   
   A buffered `FixFlags.All` event goes from 192,937 to 17,578 ns on this 
machine,
   both sides built as netstandard2.0. The remainder is `FixFlags.LocationInfo`,
   which is untouched here.
   
   Two related changes in the same method:
   
   - `Environment.UserName`, the fallback when `WindowsIdentity` is unusable, is
     also cached; it measured 33.8 us per call. Impersonation does not apply on
     that path.
   - The `SecurityException` handler now sets the unavailable flag, as the
     `PlatformNotSupportedException` handler already did. Under partial trust 
the
     old code threw, caught and logged once per event forever.
   
   Documentation: the `%username` pattern entry now explains the caching and
   points ASP.NET users at `%identity`, which is both cheaper and usually what 
is
   wanted because it reports the authenticated application user. The
   `BufferingForwardingAppender` manual page recommends `Partial` in its example
   instead of `All`; the surrounding comment already warned that the `All` 
default
   "may negatively impact performance enough to warrant changing it", and
   `LocationInfo` costs 6.9 us and 14 kB per event.
   
   `LogicalThreadContextProperties` no longer stores an empty dictionary just to
   replace it on the next line, and no longer clones on removal of an absent 
key.
   Both are cleanups; neither changes the allocation profile of the common
   set/remove pattern.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to