在那里搜索字符串性能问题并不缺乏,但我仍然无法从最好的方法中做出正面或反面。
长话短说,我已经承诺从4NT转向PowerShell。在离开4NT时,我将错过控制台超快速字符串搜索实用程序,它随附了一个名为FFIND的实用程序。我决定使用我的基本C#编程技巧来尝试创建我自己的实用程序,以便在PowerShell中使用同样快。
到目前为止搜索结果在100个目录中的字符串搜索中,其中一些1000个文件非常大,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);
}
}
}
}
答案 0 :(得分:1)
如果您想加快代码运行,请运行性能分析,看看花费的时间是多少。我几乎可以保证这里最长的一步将是
fileline.Contains(word)
在每个文件的每一行上调用此函数。天真地搜索字符串中的单词可以采用len(字符串)* len(单词)比较。
您可以编写自己的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可能是最符合您需求的。