C# GC经常触发这种情况是正常的吗?
今天我注意到,我制作的一个小程序在程序生命周期的前10~20秒内经常触发GC。之后,它几乎再也不会触发。 在这段时间内,只有1个函数运行,如下所示。获取约2k个文件路径,并过滤掉其中的大部分C# GC经常触发这种情况是正常的吗?,c#,garbage-collection,C#,Garbage Collection,今天我注意到,我制作的一个小程序在程序生命周期的前10~20秒内经常触发GC。之后,它几乎再也不会触发。 在这段时间内,只有1个函数运行,如下所示。获取约2k个文件路径,并过滤掉其中的大部分 public static string[] FilterFiles(string path) { // Fetch the files from given directory var files = Directory.GetFiles(path);
public static string[] FilterFiles(string path)
{
// Fetch the files from given directory
var files = Directory.GetFiles(path);
// Delete all files that are to small
foreach (string file in files)
{
string fullFile = default(string);
try
{
fullFile = File.ReadAllText(file);
}
catch
{
continue;
}
if (fullFile.Length < Settings.MinimumFileSize)
{
File.Delete(file);
}
}
// Obtain the new list without the small files
List<string> cleanFiles = new List<string>(Directory.GetFiles(path));
List<string> cleanReturn = new List<string>(Directory.GetFiles(path));
// Remove files we have handled before
foreach (string file in cleanFiles)
{
if (File.Exists(Settings.ExtractFolder + "\\" + file.Substring(file.LastIndexOf('\\') + 1) + "_Extract.xml"))
{
cleanReturn.Remove(file);
}
}
return cleanReturn.ToArray();
}
公共静态字符串[]过滤器文件(字符串路径)
{
//从给定目录获取文件
var files=Directory.GetFiles(路径);
//删除所有太小的文件
foreach(文件中的字符串文件)
{
string fullFile=默认值(字符串);
尝试
{
fullFile=File.ReadAllText(文件);
}
抓住
{
继续;
}
if(fullFile.Length
GC在这段时间内经常触发这种情况正常吗?嗯,是的。您正在创建大量生命周期很短的对象,这些对象将尽快被处理 尽量不要读取整个文件。相反,只是 这里您将枚举目录列表两次,这也是不必要的:
List<string> cleanFiles = new List<string>(Directory.GetFiles(path));
List<string> cleanReturn = new List<string>(Directory.GetFiles(path));
在那里使用
StringBuilder
或string.Format
,并尽可能多地在前面执行操作。您真的不需要读取整个文件来查找其长度。只需执行:long length=newfileinfo(file).length代码>
通过使用目录。EnumerateFiles(path)
,也可以枚举文件,而无需将所有文件名读入数组
我想你可以这样重写你的整个函数:
public static IEnumerable<string> FilterFiles(string path)
{
foreach (string file in Directory.EnumerateFiles(path))
{
if (new FileInfo(file).Length < Settings.MinimumFileSize)
File.Delete(file);
else if (!File.Exists(Settings.ExtractFolder + "\\" + file.Substring(file.LastIndexOf('\\') + 1) + "_Extract.xml"))
yield return file;
}
}
或者,如果要在应用其余逻辑之前强制删除所有小文件,请先使用ToArray()
,然后再使用foreach
:
foreach (string file in FilterFiles(myPath).ToArray())
...
但是要回答你的问题:是的,如果你创建了很多小对象,GC可能会经常运行。如果您创建了一些大字符串,它将特别运行:您正在读取到内存中的文件有多大?这会导致性能下降吗?您正在操作的字符串有多长?@dotctor强制关闭gc可节省约2秒。所以是的。@Theodoroschatzigannakis文件路径,<100个字符不读取整个文件,但使用文件信息将其减少到仅3个GC。谢谢
foreach (string file in FilterFiles(myPath))
...
foreach (string file in FilterFiles(myPath).ToArray())
...