C# 搜索字符串只在第一次搜索时需要很长时间?

C# 搜索字符串只在第一次搜索时需要很长时间?,c#,string,performance,C#,String,Performance,搜索字符串性能问题的方法很多,但我仍然不知道最好的方法是什么 长话短说,我已承诺从4NT迁移到PowerShell。在离开4NT时,我将错过它附带的控制台超级快速字符串搜索实用程序FFIND。我决定用我基本的C#编程技巧尝试创建一个我自己的实用程序,在PowerShell中使用,速度也一样快 到目前为止,对100个目录中的1000个文件(其中一些文件相当大)进行字符串搜索的搜索结果为FFIND 2.4秒,my utility为4.4秒。。。。。在我至少跑过一次之后 我第一次运行它们时,它几乎是在

搜索字符串性能问题的方法很多,但我仍然不知道最好的方法是什么

长话短说,我已承诺从4NT迁移到PowerShell。在离开4NT时,我将错过它附带的控制台超级快速字符串搜索实用程序FFIND。我决定用我基本的C#编程技巧尝试创建一个我自己的实用程序,在PowerShell中使用,速度也一样快

到目前为止,对100个目录中的1000个文件(其中一些文件相当大)进行字符串搜索的搜索结果为FFIND 2.4秒,my utility为4.4秒。。。。。在我至少跑过一次之后

我第一次运行它们时,它几乎是在同一时间运行的,但我的运行时间超过一分钟?这是什么?图书馆的加载?文件索引?我的代码是否有问题?我不介意再等一段时间,但差别已经非常大,如果有更好的语言或方法,我宁愿现在就开始走这条路,以免我投资太多

我需要选择另一种语言来编写快速的字符串搜索吗

我需要使用这个工具在1000个文件中搜索web代码、C#代码和另一种使用文本文件的安抚语言中的字符串。我还需要能够使用此实用程序在非常大的日志文件(MB大小)中查找字符串

class Program
{
    public static int linecounter;
    public static int filecounter;
    static void Main(string[] args)
    {
        //
        //INIT
        //
        filecounter = 0;
        linecounter = 0;
        string word;
        // Read properties from application settings.
        string filelocation = Properties.Settings.Default.FavOne;
        // Set Args from console.
        word = args[0];
        //
        //Recursive search for sub folders and files
        //
        string startDIR;
        string filename;
        startDIR = Environment.CurrentDirectory;
        //startDIR = "c:\\SearchStringTestDIR\\";
        filename = args[1];
        DirSearch(startDIR, word, filename);

        Console.WriteLine(filecounter + " " + "Files found");
        Console.WriteLine(linecounter + " " + "Lines found");
        Console.ReadKey();
    }

    static void DirSearch(string dir, string word, string filename)
    {
        string fileline;
        string ColorOne = Properties.Settings.Default.ColorOne;
        string ColorTwo = Properties.Settings.Default.ColorTwo;
        ConsoleColor valuecolorone = (ConsoleColor)Enum.Parse(typeof(ConsoleColor), ColorOne);
        ConsoleColor valuecolortwo = (ConsoleColor)Enum.Parse(typeof(ConsoleColor), ColorTwo);

        try
        {
            foreach (string f in Directory.GetFiles(dir, filename))
            {
                StreamReader file = new StreamReader(f);
                bool t = true;
                int counter = 1;
                while ((fileline = file.ReadLine()) != null)
                {
                    if (fileline.Contains(word))
                    {
                        if (t)
                        {
                        t = false;
                        filecounter++;
                        Console.ForegroundColor = valuecolorone;
                        Console.WriteLine(" ");
                        Console.WriteLine(f);
                        Console.ForegroundColor = valuecolortwo;
                        }
                        linecounter++;
                        Console.WriteLine(counter.ToString() + ". " + fileline);
                    }
                    counter++;
                }
                file.Close();
                file = null;
            }
            foreach (string d in Directory.GetDirectories(dir))
            {
                //Console.WriteLine(d);
                DirSearch(d,word,filename);
            }

        }
        catch (System.Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}
}

如果你想加快你的代码运行性能分析,看看什么是最花时间。我几乎可以保证这里最长的一步是

fileline.Contains(word)
该函数在文件的每一行、每一个文件上都被调用。天真地搜索字符串中的单词可以进行len(字符串)*len(单词)比较

您可以编写自己的Contains方法,该方法使用更快的字符串比较算法。谷歌搜索“快速字符串精确匹配”。您可以尝试使用正则表达式,看看这是否能提高性能。但我认为您可以尝试的最简单优化是:

不要每行都读。创建一个包含文件所有内容的大字符串

StreamReader streamReader = new StreamReader(filePath, Encoding.UTF8);
string text = streamReader.ReadToEnd();
在此基础上运行

如果您需要一个文件中的所有匹配项,那么您需要使用以下内容

使用regex获取单个文件的所有匹配项后,可以迭代此匹配项集合(如果存在任何匹配项)。对于每个匹配,您可以通过编写一个函数来恢复原始文件的行,该函数从“匹配对象索引”属性向前和向后读取“\n”字符。然后输出这两个换行符之间的字符串,以获得您的换行符

我保证这会快得多

如果你想更进一步,我注意到以下几点:

从循环外部删除try-catch语句。只在你需要的地方使用它。我根本不会用它

还要确保你的系统正在运行,ngen。大多数设置通常都有此功能,但有时ngen没有运行。您可以在process explorer中看到该流程。Ngen生成C#managed字节码的本机映像,因此代码不必每次都进行解释,而是可以本机运行。这大大加快了C#的速度

编辑

其他要点: 为什么第一次和后续运行时间之间存在差异?看起来像是缓存。操作系统可以缓存目录、文件、运行和加载程序的请求。通常在第一次跑步后会看到加速。Ngen也可能在这里发挥作用,在第一次运行编译后生成本机映像,然后将其存储在本机映像缓存中


总的来说,我觉得C#的性能太多变了,我不喜欢。如果建议的优化不令人满意,并且您希望获得更一致的性能结果,请尝试另一种语言——一种不是“托管”的语言。C可能最适合您的需要。

如果您想加快代码运行速度,请运行性能分析,看看什么花费的时间最多。我几乎可以保证这里最长的一步是

fileline.Contains(word)
该函数在文件的每一行、每一个文件上都被调用。天真地搜索字符串中的单词可以进行len(字符串)*len(单词)比较

您可以编写自己的Contains方法,该方法使用更快的字符串比较算法。谷歌搜索“快速字符串精确匹配”。您可以尝试使用正则表达式,看看这是否能提高性能。但我认为您可以尝试的最简单优化是:

不要每行都读。创建一个包含文件所有内容的大字符串

StreamReader streamReader = new StreamReader(filePath, Encoding.UTF8);
string text = streamReader.ReadToEnd();
在此基础上运行

如果您需要一个文件中的所有匹配项,那么您需要使用以下内容

使用regex获取单个文件的所有匹配项后,可以迭代此匹配项集合(如果存在任何匹配项)。对于每个匹配,您可以通过编写一个函数来恢复原始文件的行,该函数从“匹配对象索引”属性向前和向后读取“\n”字符。然后输出这两个换行符之间的字符串,以获得您的换行符

我保证这会快得多

如果你想更进一步,我注意到以下几点:

从循环外部删除try-catch语句。只在你需要的地方使用它。我根本不会用它

还要确保你的系统正在运行,ngen。大多数设置通常都有此功能,但有时ngen没有运行。您可以在process explorer中看到该流程。Ngen生成C#managed字节码的本机映像,因此代码不必每次都进行解释,而是可以本机运行。这大大加快了C#的速度

编辑

其他要点: 为什么第一次和后续运行时间之间存在差异?看起来像是缓存。操作系统可以缓存目录、文件、运行和加载程序的请求。通常是一个se