delphi - 扫描文件夹/子文件夹/文件时如何减少CPU使用率?

标签 delphi

我开发了一个应用程序,可以扫描基本上所有地方的文件或文件列表。 当我扫描像 10 000 个文件和子文件这样的小文件夹时,没有问题。但是,当我扫描包含超过 100 000 个项目的整个用户文件夹时,我的处理器负担非常重。它占用了我处理器大约 40% 的电量。

有没有办法优化此代码,使其使用更少的 CPU?

procedure GetAllSubFolders(sPath: String);
var
  Path: String;
  Rec: TSearchRec;
begin
  try
    Path := IncludeTrailingBackslash(sPath);
    if FindFirst(Path + '*.*', faAnyFile, Rec) = 0 then
      try
        repeat
          Application.ProcessMessages;
          if (Rec.Name <> '.') and (Rec.Name <> '..') then
          begin
            if (ExtractFileExt(Path + Rec.Name) <> '') And
              (ExtractFileExt(Path + Rec.Name).ToLower <> '.lnk') And
              (Directoryexists(Path + Rec.Name + '\') = False) then
            begin
              if (Pos(Path + Rec.Name, main.Memo1.Lines.Text) = 0) then
              begin
                main.ListBox1.Items.Add(Path + Rec.Name);
                main.Memo1.Lines.Add(Path + Rec.Name)
              end;
            end;

            GetAllSubFolders(Path + Rec.Name);
          end;
        until FindNext(Rec) <> 0;
      finally
        FindClose(Rec);
      end;
  except
    on e: Exception do
      ShowMessage(e.Message);
  end;
end;

我的应用程序搜索选定文件夹和子文件夹中的所有文件,将它们压缩并将它们复制到您指定的另一个位置。

Application.ProcessMessages 命令用于确保应用程序看起来不会挂起并且用户不会将其关闭。因为例如查找 100 000 个文件可能需要一个小时左右...

我担心处理器的使用情况,内存并没有真正受到影响。

注意:备注是为了确保相同的文件不会被选择两次。

最佳答案

我发现以下性能问题:

  1. 调用Application.ProcessMessages有点贵。您正在轮询消息而不是使用阻塞等待,即 GetMessage 。除了性能问题之外,使用 Application.ProcessMessages通常表明由于各种原因导致设计不佳,通常应该避免调用它。
  2. 非虚拟列表框在处理大量文件时表现不佳。
  3. 使用备忘录控件(GUI 控件)来存储字符串列表的成本非常昂贵。
  4. 每次添加到 GUI 控件时,它们都会更新和刷新,这是非常昂贵的。
  5. Memo1.Lines.Text的评价非常昂贵。
  6. 使用Pos同样非常昂贵。
  7. 使用DirectoryExists既昂贵又虚假。搜索记录中返回的属性包含该信息。

我会进行以下更改:

  • 将搜索代码移至线程中以避免需要 ProcessMessages 。您需要设计某种方法将信息传输回主线程以便在 GUI 中显示。
  • 使用虚拟 ListView 来显示文件。
  • 将您想要搜索重复项的文件列表存储在字典中,该字典为您提供 O(1)抬头。请注意文件名不区分大小写,这是您迄今为止可能忽略的问题。这将取代备忘录。
  • 使用Rec.Attr检查项目是否是目录。即检查Rec.Attr and faDirectory <> 0 .

关于delphi - 扫描文件夹/子文件夹/文件时如何减少CPU使用率?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25301936/

相关文章:

delphi 将条件分配给对象属性

delphi - 如何在delphi 7中将INI节分配给记录

delphi - 000C50BC 数据模块中的异常 EInoutError I/O 错误 103

delphi - 限制 DBGrid 中的小数位数

MySQL 连接提示输入密码,即使它在连接字符串中

delphi - 如何将坐标保持在屏幕范围内?

delphi - Spring 框架中是否有内置的方法可以使多态容器的使用变得更容易?

delphi - 代码完成突然停止工作

delphi - 我应该何时以及如何混淆我的 Delphi 代码?

delphi - 使用带有单独 DataSetProvider 的 ClientDataSet.AppyUpdates 主从