Reputation: 2757
I have a foreach statement inside another foreach statement that is taking a really long time to iterate through. (There a lot of records). Is there a way to simplify this code? Perhaps with Linq? Here is my code:
IList<SourceCounterPartyExposure_Limit> exposures = new List<SourceCounterPartyExposure_Limit>();
foreach (SourceCounterParty counterParty in limit.SourceCounterParties)
{
foreach (SourceCounterPartyExposure_Limit exposure in counterParty.LimitExposures)
{
if (!exposures.Contains(exposure))
{
arExposures += exposure.ARExposure;
mtmExposures += exposure.MTMExposure;
volumeExposures += exposure.ConvertedVolume;
if (maxTenorExposures < exposure.MaxTenor)
{maxTenorExposures = exposure.MaxTenor; }
exposures.Add(exposure);
} // if
} // foreach
}// foreach
Upvotes: 2
Views: 1841
Reputation: 2000
One of possible reasons to slow code is this condition:
if (!exposures.Contains(exposure))
If final order or items doesn't matter or you can sort them later, I would suggest you replacing it with
var exposures = new HashSet<SourceCounterPartyExposure_Limit> ();
If SourceCounterPartyExposure_Limit class has good hash function, than searches should be fast (close to O(1)) and it may improve overall performance of your code a lot.
Also probably you can change algorithm to run in multiple threads and then combine results. But not sure if this is appropriate for you.
Upvotes: 0
Reputation: 61339
You can certainly simplify the code:
IEnumerable<Exposure> exposures =
limit.SourceCounterParties.SelectMany(e => e.LimitExposures).Distinct()
Collapses both your loops and the if statement. You can foreach
over that and run your code:
foreach (Exposure exposure in exposures)
{
arExposures += exposure.ARExposure;
mtmExposures += exposure.MTMExposure;
volumeExposures += exposure.ConvertedVolume;
if (maxTenorExposures < exposure.MaxTenor)
{maxTenorExposures = exposure.MaxTenor;
}
That being said, its still a big enumeration, you aren't going to gain a ton of speed here.
Upvotes: 3
Reputation: 39277
Try a single loop over:
limit.SourceCounterParties.SelectMany(x => x.LimitExposures).Distinct()
That way you are (i) only getting distinct records back from the database and (ii) are allowing Entity Framework to translate your query into something that executes on the database.
You could also use Sum
and Max
to create a single query that would execute on the database.
Upvotes: 2