C# 提高程序效率?

标签 c# visual-studio-2010 c#-4.0 file-io streamreader

我正在开发一个 C# 程序,该程序读取非常大的文件并检查它们的不同属性和字段。我一直在测试少于 100 万行的文件,它按预期执行。我最近在一个 250 万行的文件上进行了测试,花了 4 个小时才跑完。

我正在使用自定义阅读功能来读取每个字符,以便我可以找到所有 CR 和 LF,因为每一行都包含它们非常重要。我单独测试了阅读功能,阅读文件大约需要 14 分钟,我认为这足以阅读 250 万行 1500 个字符中的每个字符。我将包括我的阅读功能,但这似乎不是导致问题的原因。

我的阅读函数将每个字符添加到一个字符串中,然后检查字符串中的不同值。例如,行长度是否正确,文件是否包含标题,以及标题是否包含正确的值。以及特定值,例如字符位置 403-404 是一个数字,字段 1250-1300 是否不为空等。

我的问题是,我可以做些什么来找出导致程序变慢并提高程序效率的原因?我试过检查每行循环开始和结束的时间,它似乎没有改变。但是,每 100,000 个花费的时间明显比前一个长。例如,处理 10,000 到 20,000 行用了不到 3 秒,而 830,000 到 840,000 行用了大约 35 秒。我考虑过尝试使用多个线程,但我认为这对我从文件中读取行没有帮助。想法?谢谢您的帮助!

    static void ReadMyLine(ref string currentLine, string filePath, ref int asciiValue, ref Boolean isMissingCR, ref Boolean isMissingLF, ref Boolean isReversed, ref StreamReader file)
    {
        Boolean endOfRow = false;
        isMissingCR = false;
        isMissingLF = false;
        isReversed = false;

        currentLine = "";

        while (endOfRow == false)
        {
            asciiValue = file.Read();

            if (asciiValue == 10 || asciiValue == 13)
            {
                int asciiValueTemp = file.Peek();

                if (asciiValue == 13 && asciiValueTemp == 10)
                {
                    endOfRow = true;
                    asciiValue = file.Read();
                }
                else if (asciiValue == 10 && asciiValueTemp == 13)   // CRLF Reversed
                {
                    asciiValue = file.Read();
                    endOfRow = true;
                    isReversed = true;
                }
                else if (asciiValue == 10)                           // Missing CR
                {
                    isMissingCR = true;
                    endOfRow = true;
                }
                else if (asciiValue == 13)                           // Missing LF
                {
                    isMissingLF = true;
                    endOfRow = true;
                }
                else
                    endOfRow = true;
            }
            else if (asciiValue != -1)
                currentLine += char.ConvertFromUtf32(asciiValue);
            else
                endOfRow = true;
        }
    }

最佳答案

这是我寻找的第一个东西,也是我要更改的第一个东西:

currentLine += char.ConvertFromUtf32(asciiValue);

不要那样做。在循环中使用字符串连接会杀死 性能 - 您会得到 O(N2) 的复杂度。请改用 StringBuilder。参见 my article on when to use StringBuilder以获得更多解释。

您可以做的事情可能更多,但只需更改为使用 StringBuilder 就会巨大改进:

StringBuilder builder = new StringBuilder();
while (...)
{
    ...
    builder.Append(char.ConvertFromUtf32(asciiValue));
}
currentLine = builder.ToString();

不清楚为什么你有这么多 ref 参数。你为什么要传入 asciiValue ?为什么要通过引用传递 StreamReader?任何使用这么多 ref 参数的东西都让我非常紧张 - 为什么你没有一个类型来封装你真正想要从方法返回的所有内容?

您可能想阅读我的 article on parameter passing更好地理解 ref

关于C# 提高程序效率?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7362987/

相关文章:

asp.net-mvc - .Net 4内存缓存类和用户 session

c# - DataGridView 在行更改时保存更改

c# - 如何为多处理器机器编译 C#? (使用 VS 2010 或 csc.exe)

asp.net-mvc - ModelState.IsValid 是假的 - 但哪一个 - 简单的方法

c# - 使用 Parallel for each 获取堆栈溢出异常,这是由于线程安全吗?

.net - 单元测试项目找不到被测程序集(或依赖项)

c# - 按钮点击事件

c# - 使用日历选择器后按钮控件不参与

c# - Ajax.BeginForm 未在 MVC 中使用 jQuery UI 对话框捕获 OnSuccess?

.net - CA1303,DoNotPassLiteralsAsLocalizedParameters,但我实际上不是