SYSK 106: The Cost of Using WindowsPrincipal


Did you know that using WindowsPrincipal.IsInRole is ~40+% slower than doing the same work yourself?  Run the code below and you’ll see …  Don’t take me wrong – I do not suggest you avoid using IsInRole call; after all a single call is so fast on most computers that it is not even measurable using a timer…  It’s just nice to know the cost of doing business J


 


public bool IsInRoleCustom(System.Security.Principal.WindowsIdentity wi, string role)


{


    bool result = false;


 


    System.Security.Principal.IdentityReference id = new System.Security.Principal.NTAccount(role).Translate(typeof(System.Security.Principal.SecurityIdentifier));


   


    foreach (System.Security.Principal.IdentityReference group in wi.Groups)


    {


        if (group.Value == id.Value)


        {


            result = true;


            break;


        }


    }


 


    return result;


}


 


public bool IsInRoleSystem(System.Security.Principal.WindowsIdentity wi, string role)


{


    return new System.Security.Principal.WindowsPrincipal(wi).IsInRole(role);


}


 


private void Form1_Load(object sender, EventArgs e)


{


    System.Security.Principal.WindowsIdentity wi = System.Security.Principal.WindowsIdentity.GetCurrent();


   


    string role = “Guests”;


    int cnt = 20000;


 


    long t11, t12, t21, t22;


 


    t11 = DateTime.Now.Ticks;


 


    for (int i = 1; i < cnt; i++)


    {


        bool result = IsInRoleCustom(wi, role);


    }


 


    t12 = DateTime.Now.Ticks;


 


 


    t21 = DateTime.Now.Ticks;


 


    for (int i = 1; i < cnt; i++)


    {


        bool result = IsInRoleSystem(wi, role);


    }


 


    t22 = DateTime.Now.Ticks;


 


 


    System.Diagnostics.Debug.WriteLine((t12-t11).ToString());


    System.Diagnostics.Debug.WriteLine((t22-t21).ToString());


    System.Diagnostics.Debug.WriteLine(((t22 – t21)/TimeSpan.TicksPerMillisecond).ToString());


    System.Diagnostics.Debug.WriteLine(((float) (t22 – t21) / (t12 – t11)).ToString());


}


 


 

Comments (6)

  1. Lauren Smith says:

    The question, then, is Why?  What else is the system call doing that’s taking up that extra time?

  2. irenake says:

    The "extra time" is very little, measurable in CPU cycles, but not even with a high resolution timer.  The things to account for are:  creating WindowsPrincipal instance, and the fact that my simplistic code simply compares group SIDs where as IsInRole (I believe) uses identity.TokenHandle to check for membership.

  3. Lauren Smith says:

    I’ve been in optimization mode for the past couple weeks, so my viewpoint is definitely skewed.  When I see 40% possible improvement in time, it makes me giddy.  Now that improvement may only end up a couple cycles in the long run, and as we all know, we shouldn’t prematurely optimize, but if funcX() returns the same boolean value as funcY() with the same parameters and there are no other side effects that differentiate the two functions, I’d take those extra cycles and apply them elsewhere.

    Is there something else going on in the system code that is overlooked in the custom code?  Some edge case that won’t get handled correctly by simple SID comparison?

    Anyway, I just thought it was interesting about the performance difference between system and custom code.  For any very specific task like this, you’d expect the system implementer to have selected the ideal implementation.  When the ideal implementation isn’t the fastest, it’s interesting to hear the reasons why.

  4. Liora says:

    Hi,

    I could not find Group  in WindowsIdentity

    (as in your code – wi.Groups).

    Also I could not find "System.Security.Principal.IdentityReference".

    In what vesion of .NET is this available?

    Thanks a lot.

  5. You’ve been kicked (a good thing) – Trackback from DotNetKicks.com

Skip to main content