Как я могу улучшить производительность при вставке в список во время цикла C# - PullRequest
1 голос
/ 25 февраля 2020

Как я могу улучшить производительность нижеприведенного блока кода. В списке DifferentUniqueIDs содержится более 10000 записей. Я пробовал параллельное выполнение, но это не дает большой разницы. Есть ли еще место для оптимизации

for (int i = 0; i < distinctUniqueIDs.Count; i++)
{
    long distinctUniqueID = distinctUniqueIDs[i];
    try
    {
        if (!SmartAppConfigMapDict.ContainsKey(distinctUniqueID))
        {
            appconfigTemp = new SmartAppconfigRootElementMap();
            filteredList = validAppConfig.Where(m => m.UniqueID == distinctUniqueID);

            if (filteredList?.Count() > 0)
            {
                appconfigTemp.AppConfig = filteredList.First();
                appconfigTemp.RootElements = filteredList.ToDictionary(m => 
                    m.RootElementVersionID, m => m.RootElementName);
                appconfigTemp.RootElementPrimaryKeyMaps = filteredList.ToDictionary(m => 
                    m.RootElementVersionID, m => new RootElementPrimaryKeyMap
                {
                    RootElementName = m.RootElementName,
                    RootElementVersionID = m.RootElementVersionID,
                    ChildElementDesc = m.ChildElementDesc,
                    ChildElementName = m.ChildElementName,
                    ChildElementPath = m.ChildElementPath,
                    ActualRootElementVersionID = m.ActualRootElementVersionID,
                    ActualRootElementName = m.ActualRootElementName
                });

                SmartAppConfigMapDict.Add(distinctUniqueID, appconfigTemp);

                if (queryRootElementMap.ContainsKey(appconfigTemp.AppConfig.QueryID))
                {
                    queryRootElementMap[appconfigTemp.AppConfig.QueryID]
                        .Add(appconfigTemp);
                }
                else
                {
                    appConfigRootMapSubList = new List<SmartAppconfigRootElementMap>();
                    appConfigRootMapSubList.Add(appconfigTemp);
                    queryRootElementMap.Add(appconfigTemp.AppConfig.QueryID, 
                        appConfigRootMapSubList);
                }
            }
        }
    }
    catch (Exception)
    {
        continue;
    }
}

1 Ответ

2 голосов
/ 25 февраля 2020

Преступник должен быть

filteredList = validAppConfig.Where(m => m.UniqueID == distinctUniqueID);

Во-первых, LINQ Where - это неэффективный метод с линейной временной сложностью O (N). Использование таких методов внутри циклов не рекомендуется.

Во-вторых, из-за отложенного выполнения LINQ вышеупомянутый линейный поиск выполняется несколько раз - в основном каждым оператором, применяемым к filteredList - filteredList?.Count(), filteredList.First() и 2 filteredList.ToDictionary(…) звонков.

Что вы можете сделать, это подготовить заранее структуру данных быстрого поиска на основе ha sh (например, Lookup ) вне l oop и используйте его внутри.

например, добавьте что-то подобное за пределами l oop:

var validAppConfigsByUniqueID = validAppConfig.ToLookup(m => m.UniqueID);

и внутри замените

filteredList = validAppConfig.Where(m => m.UniqueID == distinctUniqueID);

if (filteredList?.Count() > 0)

на

var filteredList = validAppConfigsByUniqueID[distinctUniqueID];

if (filteredList.Any())

Обратите внимание, что операция validAppConfigsByUniqueID[distinctUniqueID] имеет постоянную сложность по времени O (1). И возвращаемое перечислимое уже буферизовано, поэтому повторение его несколько раз не является проблемой.

...