Click here to Skip to main content
15,885,757 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am making few API calls to get data and loop through to add objects to a list which is working fine. However, because the API is returning more than 12000 records, my function takes more than 30 minutes to execute which is slowing the system performance.

How can I add straight to a list without looping throughout each list object?

This is my current code

What I have tried:

<pre>List<Destination> destinations = GetDestinationByCountryCode(rateSheetSummaries.FirstOrDefault().CountryCode).Where(d => d.Used == true).ToList();
                    foreach (var rateSheetSummary in rateSheetSummaries)
                    {
					    
                        List<Destination> insertDestinations = destinations.Where(d => d.Description.ToLower().Trim().Contains(rateSheetSummary.DestinationLookup.ToLower().Trim())).ToList();

                        foreach (var destination in insertDestinations)
                        {
                            Rate rate = new Rate()
                            {
                                DestinationGroup = rateSheetSummary.Description,
                                Description = rateSheetSummary.Description,
                                DestinationId = destination.DestinationId,
                                Country = rateSheetSummary.CountryCode,
                                TariffId = tariffId,
                                NextPrice = rateSheetSummary.Peak,
                                Price = rateSheetSummary.Peak,
                                Interval = 1,
                                Discontinued = "N",
                                Forbidden = "N"
                            };
                            rates.Add(rate);
                        }
                    }
Posted
Updated 25-Jun-21 6:52am

I would think processing this sort of filtering on 12000 records is unfortunately going to be slow. The bloat in this process is dependent on how many entries in your rateSheetSummaries collection. If you have one entry in there, then you're looking at 1x12000 searches; otherwise, if you have 100 then this expands greatly up to 1,200,000 searches. Even worse is that every one of these searches performs the following:
C#
d.Description
  .ToLower()
  .Trim()
  .Contains(rateSheetSummary
    .DestinationLookup
    .ToLower()
    .Trim())

That's a lot of operations to be doing on every single item. Instead, think about ways to optimise this particular operation. First, the Contains() method has an overload for whether to be case insensitive. Second, consider whether using Trim() on every d.Description is needed. Third, you could cache the DestinationLookup prior to the search. Fourth, the call to ToList() on the results of the search seems unnecessary. Something like:
C#
foreach (var rateSheetSummary in rateSheetSummaries)
{
  string search = rateSheetSummary.DestinationLookup.Trim();					    
  IEnumerable<Destination> insertDestinations = destinations
    .Where(d => d.Description
      .Contains(search, StringComparison.InvariantCultureIgnoreCase));

  foreach (var destination in insertDestinations)
  {
    Rate rate = new Rate()
    {
      DestinationGroup = rateSheetSummary.Description,
      Description = rateSheetSummary.Description,
      DestinationId = destination.DestinationId,
      Country = rateSheetSummary.CountryCode,
      TariffId = tariffId,
      NextPrice = rateSheetSummary.Peak,
      Price = rateSheetSummary.Peak,
      Interval = 1,
      Discontinued = "N",
      Forbidden = "N"
    };
    
    rates.Add(rate);
  }
}

At the end of the day though, this might only provide a minor improvement to performance. The main issue here is iterating over so many records.
 
Share this answer
 
Comments
Nkhanedzeni 25-Jun-21 5:36am    
It is giving me this error: "No overload method 'Contains' takes two arguments"
Chris Copeland 25-Jun-21 5:45am    
Ah my bad, looks like that's a new addition to the C# family. Instead you can use the IndexOf method with the same option: .IndexOf(search, StringComparison.InvariantCultureIgnoreCase) >= 0
Nkhanedzeni 25-Jun-21 5:40am    
I have fixed it by removing extra param.

How can i optimize this as well

foreach (var destination in insertDestinations)
{
Rate rate = new Rate()
{
DestinationGroup = rateSheetSummary.Description,
Description = rateSheetSummary.Description,
DestinationId = destination.DestinationId,
Country = rateSheetSummary.CountryCode,
TariffId = tariffId,
NextPrice = rateSheetSummary.Peak,
Price = rateSheetSummary.Peak,
Interval = 1,
Discontinued = "N",
Forbidden = "N"
};

rates.Add(rate);
}
Chris Copeland 25-Jun-21 5:51am    
I'm not sure if there's much you can do to improve that. The only thing you might find is that you end up inserting duplicates into the list, so you could look at using a Dictionary<> instead and use a composite key to work out whether it's been inserted already. Otherwise, if your result sets are containing thousands of records then you'll have to cater for it taking a while!
You might speed up things using Parallel.ForEach, see this article:
Process your list in parallel to make it faster in .NET[^]
 
Share this answer
 
Comments
Nkhanedzeni 25-Jun-21 15:07pm    
It seems Parallel.ForEach will make things easier. I did a bit of digging and i come up with the below. I want to add to this list
List<rate> rates = new List<rate>();

Parallel.ForEach(insertDestinations, destination => {

//Now i am not sure how i can continue base on my Foreach statement. Can you please assist?
});

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900