if,else if if mapping性能

时间:2013-09-24 15:03:30

标签: c# performance if-statement mapping

我有一个表现问题。

我正在解析大型文本文件(账单),并根据账单上是否出现某些文字,将服务提供商的名称分配给变量。

这是我正在做的一小部分样本(不要笑,我知道它很乱)。总而言之,如果是,那么大约有250个。

if (txtvar.BillText.IndexOf("SWGAS.COM") > -1)
   {
       txtvar.Provider = "Southwest Gas";
   }
else if (txtvar.BillText.IndexOf("georgiapower.com") > -1)
   {
       txtvar.Provider = "Georgia Power";
   }
else if (txtvar.BillText.IndexOf("City of Austin") > -1)
   {
       txtvar.Provider = "City of Austin";
   }

//依次250次

因为它变得如此之大,我决定采用不同的方法来变得更清洁,更有效率。我最终实现了一个映射,我将其存储在外部.psv文件中。

我将该映射保存到变量(这只运行一次,大约需要35毫秒......

var providerMap =
                    System.IO.File.ReadLines(@"U:\Program\ApplicationFiles\ProvidersList.psv")
                    .Select(line => line.Split('|'))
                    .Select(parts => new Provider() { Pattern = parts[0], Name = parts[1] }).ToList();

...然后循环遍历每个账单(分配提供者需要大约2毫秒,而if语句花费的时间不到一半......

foreach (string bills in files)
                                {
                                    string Provider = providerMap.First(p => txtvar.BillText.IndexOf(p.Pattern) > -1).Name;
                                    OtherStuff();
                                }

虽然这个解决方案更清洁,但令人惊讶的是比250+要慢得多,如果是的话。我使用秒表方法找出clean方法实际上是数百个if语句的两倍慢。 (我测试了if语句的开头和结尾以及具有类似结果的映射的账单)

有人可以向我解释一下吗?也许我做错了什么?谢谢!

3 个答案:

答案 0 :(得分:2)

读取外部文件肯定会让你失望。我假设你只读了一次,但它仍然会减慢你的速度。

1)您是否尝试过缓存文件的内容,以便不再需要阅读?如果映射没有太大变化,这可能会有所改善。

2)另外,为什么不尝试将映射存储在Dictionary对象(或类似结构)中?如果您愿意,可以将它放在单独的类文件中。这是一种硬编码解决方案,不确定它在您的系统中的效果如何。

答案 1 :(得分:1)

循环展开是一种通过将循环转换为语句序列来提高性能的技术。一个简单的例子

for(int i = 0; i < 3; i++)
{
    Console.WriteLine(i);
}

可以展开到

Console.WriteLine(0);
Console.WriteLine(1);
Console.WriteLine(2);

这样做有各种复杂的技术,但重点是减少循环变量的增量数,条件的评估和机器代码中的跳转指令。请注意,这种技术并不总是一种可靠的性能提升。有关更多讨论和示例,请参阅loop unwinding

你走了另一条路。您已经使用了很长的if-else构造并将其转换为

string Provider = providerMap.First(p => txtvar.BillText.IndexOf(p.Pattern) > -1).Name;

现在所有First正在做的就是这样做(注意First会抛出没有项目匹配的情况):

Provider found = null;
foreach(var provider in providerMap)
{
    if (txtvar.BillText.IndexOf(provider.Pattern) > -1)
    {
        found = provider;
        break;
    }
}

所以你可以看到你走了相反的道路:从一系列陈述到一个循环。

我认为你已经获得了一些你未提及的东西,即能够在不重新编译代码的情况下添加提供者,这可能很方便。

答案 2 :(得分:0)

我会选择第三个选项,

1-它更具可读性

少了2个代码,也可以是性能+1。

3-更易于维护

4- dll中没有字符串,这也减小了dll的大小