1

那里不乏搜索字符串性能问题,但我仍然无法确定最佳方法是什么。

长话短说,我已经承诺从 4NT 转移到 PowerShell。在离开 4NT 时,我会想念它附带的名为 FFIND 的控制台超级快速字符串搜索实用程序。我决定使用我的基本 C# 编程技能来尝试创建我自己的实用程序,以便在 PowerShell 中使用,它同样快。

到目前为止,在跨越几个 1000 个文件的 100 个目录中进行字符串搜索的搜索结果,其中一些文件非常大,是 FFIND 2.4 秒和我的实用程序 4.4 秒.....在我至少运行了一次之后??? ?

我第一次运行它们 FFIND 几乎在同一时间运行,但我的运行时间超过一分钟?这是什么?加载库?文件索引?我在我的代码中做错了吗?我不介意再等一会儿,但差异非常大,如果有更好的语言或方法,我宁愿现在就开始走这条路,以免投入过多。

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

我需要使用此实用程序在 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);
        }
    }
}
}
4

1 回答 1

1

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

fileline.Contains(word)

在文件的每一行,每个文件上都会调用此函数。天真地在字符串中搜索单词可以进行 len(string) * len(word) 比较。

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

不要阅读每一行。制作一个包含文件所有内容的大字符串。

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

运行包含在此。

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

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

这会快得多,我保证。

如果您想走得更远,我注意到的一些事情是:

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

还要确保您的系统正在运行,ngen。大多数设置通常都有这个,但有时 ngen 没有运行。您可以在流程资源管理器中查看流程。Ngen 生成 C# 托管字节码的本机映像,因此不必每次都解释代码,而是可以本机运行。这大大加快了 C# 的速度。

编辑

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

总的来说,我发现 C# 的性能变化太大,不符合我的喜好。如果建议的优化不令人满意并且您想要更一致的性能结果,请尝试另一种语言 - 一种不是“托管”的语言。C 可能最适合您的需求。

于 2012-12-20T01:31:37.093 回答