There's a piece of code I've been fiddling with to see if I can speed it up because it definitely shouldn't take 3.8 to 4.4 seconds to process about 1400 UserPrincipals.
I've used stopwatches to time different pieces of the function when I noticed that the pieces don't add up to the timer measuring the entire function. The gap is relatively dramatic and I can't figure out where it's coming from. I'd appreciate any insight.
The SamAccountName measurement is because I found some info that it can potentially be slow because of how the getter of the property is implemented, for anyone wondering.
Function code:
private static ConcurrentDictionary<string, User> ProcessUsers(List<UserPrincipal> users)
{
ConcurrentDictionary<string, User> toReturn = new ConcurrentDictionary<string, User>(4, 2000);
Regex regex = new Regex(@"^[a-zA-Z]{3}(\d{4})$");
Parallel.ForEach(users, user =>
{
Stopwatch timerSamAccountName = new Stopwatch();
Stopwatch timerIfBlock = new Stopwatch();
Stopwatch timerTotal = new Stopwatch();
timerTotal.Start();
timerSamAccountName.Start();
string guid = user.SamAccountName;
timerSamAccountName.Stop();
Console.WriteLine($"SamAccountName done in {timerSamAccountName.Elapsed} for {user.Name}");
timerIfBlock.Start();
if (regex.IsMatch(guid))
{
User newUser = new User(user.Name, guid.ToUpper(), user.EmailAddress, user);
toReturn.TryAdd(newUser.ID, newUser);
}
timerIfBlock.Stop();
Console.WriteLine($"IF block done in {timerIfBlock.Elapsed} for {user.Name}");
timerTotal.Stop();
Console.WriteLine($"User processed in {timerTotal.Elapsed} for {user.Name}");
});
return toReturn;
}
User class:
internal class User
{
public string name { get; set; }
public string ID { get; set; }
public string email { get; set; }
public UserPrincipal? activeDirectoryHandle { get; set; }
public User(string inName = "None", string inID = "None", string inEmail = "None", UserPrincipal? adHandle = null)
{
name = inName;
ID = inID;
email = inEmail;
activeDirectoryHandle = adHandle;
}
}
Example of the discrepancy:
CodePudding user response:
The timers don't add up because you're doing work in places where some of the timers (timerSamAccountName
and timerIfBlock
) aren't running. Additionally, the work you're doing outside the timers (string interpolation and writing to the console) are the longest-running operations in the whole example. You've pretty much measured how much slower these operations are, in fact.