delphi - 减少 VCL 中花费的 CPU 时间

标签 delphi bitmap vcl

对于 MIDI 播放器来说,尽可能精确地播放音符非常重要。我从来没有完全成功过,总是责怪计时器(参见上一个线程: How to prevent hints interrupting a timer )。最近我购买了 ProDelphi 并开始测量究竟是什么消耗了这么多时间。结果非常令人惊讶,请参见下面的示例代码。

procedure TClip_View.doMove (Sender: TObject; note, time, dure, max_time: Int32);
var x: Int32;
begin
{$IFDEF PROFILE}Profint.ProfStop; Try; Profint.ProfEnter(@self,1572 or $58B20000); {$ENDIF}
   Image.Picture.Bitmap.Canvas.Pen.Mode := pmNot;
   Image.Picture.Bitmap.Canvas.MoveTo (FPPos, 0);
   Image.Picture.Bitmap.Canvas.LineTo (FPPos, Image.Height);
   x := time * GPF.PpM div MIDI_Resolution;
   Image.Picture.Bitmap.Canvas.Pen.Mode := pmNot;
   Image.Picture.Bitmap.Canvas.MoveTo (x, 0);
   Image.Picture.Bitmap.Canvas.LineTo (x, Image.Height);
   FPPos := x;
//   Bevel.Left := time * GPF.PpM div MIDI_Resolution;
{$IFDEF PROFILE}finally; Profint.ProfExit(1572); end;{$ENDIF}
end; // doMove //

测量结果为(在 Intel i7-920, 2,7Ghz 上没有调试代码):

  1. 如图所示的代码为 95 微秒
  2. 当所有内容都被注释掉时,除了现在注释掉的语句 (Bevel.Left :=) 之外,为 5.609 毫秒
  3. 当所有代码替换为 x := time * GPF.PpM div MIDI_Resolution; 时为 0.056 微秒

仅在 Bevel 上移动所消耗的 CPU 成本是仅在 Canvas 上绘图的 60 倍。这让我很惊讶。测量 1 的结果非常清晰(还有更多的事情发生),但 2 和 3 则不然。我需要向用户提供某种形式的反馈,因为播放器现在正在处理什么,钢琴卷轴上的某种线条是可接受的方式。在我不断追求减少定时事件循环中的 CPU 周期的过程中,我有一些问题:

  • 为什么沿着斜角移动要花费这么多时间?
  • 有没有办法比在位图上绘图时减少更多的 CPU 周期?
  • 有没有办法减少绘图时的闪烁?

最佳答案

你将无法改变世界,VCL 或 Windows 也无法改变。我怀疑你对那些人要求太多了......

恕我直言,你最好稍微改变一下你的架构:

  • 声音处理应在一个(或多个)独立线程中进行,并且根本不应链接到 UI(例如,不要从中发送 GDI 消息);
  • 应使用分辨率为 500 毫秒的计时器进行 UI 刷新(半秒刷新听起来就足够 react ),而不是每次发生更改时都进行刷新。

也就是说,排序器不会刷新 UI,但 UI 会定期询问排序器当前状态是什么。恕我直言,这会更顺利。

要回答您的确切问题:

  • “移动斜角”实际上是发送多条GDI消息,并由GDI堆栈(gdi32.dll)使用临时位图进行渲染;
  • 尝试使用较小的位图,或尝试使用 Direct X 缓冲区映射;
  • 在 TForm.OnCreate 事件上尝试 DoubleBuffered := true,或者使用专用组件 (TPaintBox) 以及整个组件内容的全局位图,例如用于消息 WM_ERASEBKGND

一些代码:

   procedure TMyPaintBox.WMEraseBkgnd(var Message: TWmEraseBkgnd);
   begin
     Message.Result := 1; // no erasing is necessary after this method call
   end;

关于delphi - 减少 VCL 中花费的 CPU 时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9033860/

相关文章:

delphi - 在非对话框表单上显示帮助问号按钮(biHelp)?

windows - TPageControl 获取索引

ListView 中的Android BitmapDecode

c - win32 - 如何将屏幕捕获为 8 位或 16 位位图?

android - OpenGl 中的无效位图格式

forms - FormCreate和Hide之后不会触发FormShow事件;不隐藏任务栏上的图标

delphi - 是否可以控制 JvDockServer 组件中选项卡的显示方式?

delphi - 如何将接口(interface)添加到尚未包含 TInterfacedObject 的类层次结构中?

c++ - VCL 显示不同的形式

delphi - Delphi重映射键到多个字符