EB.
EB.

Reputation: 2757

Foreach statement takes to long

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

Answers (3)

dlxeon
dlxeon

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

BradleyDotNET
BradleyDotNET

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

Ian Mercer
Ian Mercer

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

Related Questions