Exploring C# Optimization Techniques (2022)
initechsolutions.blogspot.com
initechsolutions.blogspot.com
The “expert level” technique uses an unbounded number of threads rather than utilising a thread pool.
Using concurrent objects here also seems a waste - why pay for the locking overhead? The set of all states is quite small - just create a unique set of states, pre-fill the “taxMap” in parallel, then launch a number of tasks to calculate the totals. You probably don’t even need to do the final calculation in parallel as it’s super simple.
With the approaches listed here you are calling GetSalesAndTax multiple times for the same state.
The author hasn’t realised that the essence of the problem can be distilled down to needing a call a single expensive function with a single argument once and collect the results into a hashmap.
The use of a concurrent bag is also a waste - just return the total from the task? You could return a tuple of (unique ID, total) to allow you to associate the result with a specific migrant.
ConcurrentDictionary<string, double> taxMap = new ConcurrentDictionary<string, double>();
await Task.WhenAll(migrantList
.SelectMany(m => m.StatesTraversed)
.Distinct()
.Select(async s => taxMap.TryAdd(s, await GetSalesAndUseTaxForStateAsync(s))));
migrantList.ForEach(mti => Console.WriteLine($"Total Relocation Fee: {mti.StatesTraversed.Sum(s => taxMap[s]) + mti.TotalMilesTravelled * .15}"));
This gets pretty close to negligible overhead. The above ran in 0.519s, including the .5s await time of the "API" call.I just wanted to show that there's an optimized solution that is also more concise in C#.