0

这种计数方法在一个单元测试中非常慢。可以通过并行化来改进它吗?

编辑:要清楚,我无法更改日历界面或实现。我对计数算法感兴趣。

public static int CountBusinessDays(ICalendar calendar, DateTime start, DateTime end)
{
    int nBusinessDays = 0;

    for (DateTime current = start; current <= end; current = current.AddDays(1))
    {
        if (calendar.IsBusinessDay(current))
            ++nBusinessDays;
    }

    return nBusinessDays;
}

public interface ICalendar
{
    bool IsBusinessDay(DateTime day);
}
4

2 回答 2

2

因此,从这里开始,这是一个简单的辅助方法,可以生成从给定点开始的无限天序列:

public static IEnumerable<DateTime> Days(DateTime start)
{
    while (true)
    {
        yield return start;
        start = start.AddDays(1);
    }
}

然后,我们可以使用以下方法生成代表您的范围的天数序列TakeWhile

var allDays = Days(start).TakeWhile(day => day <= end);

接下来,我们可以使用 PLINQ 来并行化每天的计算:

return allDays.AsParallel()
    .Where(day => calendar.IsBusinessDay(day))
    .Count();

请注意,计算给定日期是否为工作日可能不是特别耗时。如果是这种情况,那么管理所有不同线程的开销实际上很可能比您从并行化工作中获得的时间更多。基础集合的大小也很重要;如果它更长,那么并行化的机会就更大。AsParallel您应该通过添加/删除调用来运行一些测试,看看这是否真的是一个胜利。

于 2013-09-27T14:28:05.123 回答
0

如果您无法更改实现,那么加快速度的唯一可能方法是通过并行化(无论您是否通过应用程序代码处理多个线程)。

由于我们不知道 calendar.IsBusinessDay() 中发生了什么,我们无法告诉您它是否会更快。也许你有隐式序列化,也许你资源匮乏,也许它只是因为它不是线程安全而中断。如果您不知道答案,我可以想到 4 个选项。1)尝试并行化,看看它是否有效并且是因素。2)修改或消除测试用例,使其更快。3)投入更多/更快的硬件,4)忍受它。

于 2013-09-27T14:10:22.363 回答