搜索字符串仅第一次需要很长时间



搜索字符串性能问题的搜索不足,但我仍然无法从最佳方法中脱颖而出。

长话短说,我致力于从4NT转移到Powershell。在离开4NT时,我将错过称为ffind的游戏机超快速搜索实用程序。我已经决定使用我的基本C#编程技能来尝试创建自己的实用程序,以便在PowerShell中使用,这也同样快。

到目前为止,在几个1000个文件中,在100个目录中的字符串搜索上进行了搜索结果,其中一些文件很大,是2.4秒,我的实用程序为4.4秒.....????

我第一次运行它们会在同一时间近距离使用,但是我的时间超过一分钟?这是什么?库的加载?文件索引?我在代码中做错了什么?我不介意等待更长的时间,但是区别足够极端,如果有更好的语言或方法,我宁愿在我投入过多之前就开始那条道路。

我需要选择另一种语言来编写一个将快速照明

的字符串搜索

我有必要使用此实用程序来搜索1000个文件,以获取Web代码,C#代码和另一种使用文本文件的ProSitiatory语言中的字符串。我还需要能够使用此实用程序在非常大的日志文件(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(string) * len(word)比较。

您可以编码自己的包含方法,该方法使用更快的字符串比较算法。Google用于"快速字符串精确匹配"。您可以尝试使用正则表达式,并查看是否可以提高性能。但是我认为您可以尝试的最简单的优化是:

不要阅读每一行。制作文件的所有内容。

StreamReader streamReader = new StreamReader(filePath, Encoding.UTF8);
string text = streamReader.ReadToEnd();

运行包含。

如果您需要文件中的所有匹配项,则需要使用Regex..matches(String,String)之类的内容。

使用Regex获取单个文件的所有匹配项后,您可以在此匹配集合(如果有任何匹配项)上迭代。对于每个匹配,您可以通过编写一个从匹配对象索引属性向前读取的函数来恢复原始文件的行,并找到" n"字符的位置。然后在这两个新线之间输出该字符串,以获取您的行。

我保证这会更快。

如果您想进一步走,我注意到的某些事情是:

从循环外部删除尝试捕获语句。仅在需要的地方准确地使用它。我根本不会使用它。

还确保您的系统正在运行,NGEN。大多数设置通常都具有此功能,但有时NGEN不运行。您可以看到Process Explorer中的过程。NGEN生成C#管理字节码的本机映像,因此代码不必每次都可以解释,但可以在本地运行。这加快了c#。

编辑

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

通常,我发现C#性能太多了,无法获得我的喜好。如果建议的优化不令人满意,并且您希望更一致的性能结果,请尝试另一种语言 - 一种不是"管理"的语言。C可能是您需要的最佳。

最新更新