我有一个
Outcomes
的列表,我正在加载到内存中;这个列表有一个名为OutcomeConditions
的属性,它是每个结果的另一个条件列表。我还有一个列表Rules
,其中包含我从数据源加载到内存中的任意规则。
我的算法只过滤条件至少匹配 Rules
列表中的一个规则的结果。
使用 C# 在 .NET Core 中实现的算法是功能性的,但它是计算密集型的,因此速度很慢。结果数的上限始终为 60(称为 n),规则数的上限为 12(称为 m),对于结果条件,它最多为 3(称为 p);因此复杂度总计为 O(nmp)。
有关重要性的一些上下文:该算法是在 Web API 端点中实现的,该端点非常关键,因为它被频繁调用并在很大程度上影响用户体验。
我使用 EF Core 作为我的 ORM,我尝试了以下方法来提高这个 API 端点和底层服务的整体性能:
IQueryable<T>
.AsNoTracking()
从数据库读取只读数据,以减少不必要的跟踪开销for
而不是 foreach
或 LINQ
迭代以减少开销(因为迭代数组比在列表上迭代更快)这种改进方法是针对所用工具的机械同情,并不令人满意,因为我觉得底层算法可以改进。
这里有一些代码,特别是迭代,从外循环开始:
for (int outcomeIndex = 0; outcomeIndex < inputOdds.Length-1; outcomeIndex++)
{
var savedOutcome = await oddService.GetOutcomeByOutcomeId(inputOdds[outcomeIndex].OutcomeId);
var filteredOutcome = await conditionService.FilterOutcomeConditions(savedOutcome, umbracoGame,language, IsFilterActive);
if (filteredOutcome != null && !IsDuplicateOutcome(filteredOutcome, filteredOdds))
filteredOdds.Add(await CustomizeUmbracoOutcome(filteredOutcome));
}
外部循环遍历每个结果并调用
FilterOutcomeConditions
方法,其中一部分如下所示(并包含一个嵌套循环,用于根据规则列表验证每个结果条件):
foreach (var rule in umbracoGame.OutcomeRules)
{
var validConditions = new List<OutcomeCondition>();
if (filterActive && !rule.IsActive)
continue;
foreach (var condition in outcomeConditions)
ValidateIfConditionMeetsCurrentUmbracoRule(rule, validConditions, condition);
int numberOfRules = await GetNumberOfUmbracoRulesForOutcome(rule);
if (validConditions.Count > 0 && outcomeConditions.Count() == numberOfRules)
if (doConditionsMeetUmbracoRequirements(validConditions, rule))
{
filteredOutcome.Conditions = validConditions.Select(x=>mapper.Map<OutcomeCondition, OutcomeConditionDto>(x));
filteredOutcome.Summary = rule.Summary;
filteredOutcome.Title = rule.Title;
filteredOutcome.Thumbnail = rule.Thumbnail;
return filteredOutcome;
}
}
return null;
我想知道是否有一种方法可以优化目前在时间和空间上为 O(nmp) 的核心算法。或者,我可能忽略(或错误解释)的工具(.NET Core、EF Core 等)的任何性能增强将不胜感激。