(标题和问题已发生重大变化,因为没有一个重要部分最终与问题相关)
我有一个生成的硬盘文件树,我正在创建一个函数来突出显示文件树中扩展的每个实例。由于某种原因,在扫描期间创建的文件树之外的任何重复文件树上进行迭代可能需要至少两倍的时间。请注意,我不会在扫描期间尝试遍历文件树。
究竟是什么导致了放缓?List<FileNode>
似乎是罪魁祸首,但我不确定是什么内部机制出了问题。
我创建了一个包含 4 个文件的要点来枚举文件树并显示迭代时间的不一致:FileTreeIterationSpeedTest
具有 2m 文件和 200k 目录的驱动器的性能:
要点的输出:
Scanning...
RAM Used: 300.6 MB
Bytes: 443.7 GB
Files: 1,925,131
Folders: 156,311
Progress: 100.0%
Duration: 00:00:17
Scan complete!
Duplicating file tree...
Duplication complete!
RAM Used: 311.4 MB
Iterating: 1000
Scanned Tree: 00:03.857
Duped Tree: 00:01.409
Duped Tree is 173.6% faster
Press any key to continue...
相关代码来自FileNode.cs
:
public class FileNode {
public enum FileNodeType {
Root,
Directory,
FileCollection,
File,
}
private readonly List<FileNode> children = new List<FileNode>();
private FileNode fileCollection;
public FileNode Parent { get; private set; }
public FileNodeType Type { get; }
public long Size { get; private set; }
public string Extension { get; } = string.Empty;
public string Name { get; }
// File Collection
private FileNode() {
Type = FileNodeType.FileCollection;
Name = "<Files>";
}
// Root Node
public FileNode(string drivePath) {
Type = FileNodeType.Root;
Name = drivePath;
}
// File or Directory Node
public FileNode(Win32FindData find) {
if (!find.IsDirectory) {
Type = FileNodeType.File;
Extension = Path.GetExtension(find.cFileName);
}
else {
Type = FileNodeType.Directory;
}
Name = find.cFileName;
Size = find.Size;
}
// Duplicate Tree \w Parent
public FileNode(FileNode root) : this(root, null) {
}
// Duplicate Tree \w Parent
private FileNode(FileNode file, FileNode parent) {
Parent = parent;
Type = file.Type;
Size = file.Size;
Extension = file.Extension;
Name = file.Name;
int count = file.children.Count;
children = new List<FileNode>(count);
for (int i = 0; i < count; i++)
children.Add(new FileNode(file[i], this));
}
public void AddChild(FileNode item) {
if (item.Type == FileNodeType.File && Type != FileNodeType.FileCollection) {
if (fileCollection == null)
fileCollection = new FileNode();
fileCollection.AddChild(item);
}
else {
children.Add(item);
item.Parent = this;
}
}
public bool IsLeaf => children.Count == 0;
public int Count => children.Count;
public FileNode this[int index] => children[index];
}