减少VCL花费的CPU时间 [英] Reduce CPU time spent in VCL
问题描述
有一个MIDI播放器播放的音符为precisely尽可能是很重要的。我从来没有完全成功在于,总是指责定时器(见previous螺纹:的如何prevent提示中断定时器)。最近我获得了ProDelphi,开始测量究竟消耗了多少时间。其结果是相当惊人的,见下面的例子code。
It is important for a MIDI player to playback the notes as precisely as possible. I never quite succeeded in that, always blaming the timer (see a previous thread: How to prevent hints interrupting a timer). Recently I acquired ProDelphi and started measuring what exactly consumed that much time. The result was quite surprising, see the example code below.
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调试code,2,7Ghz):
The measurements are (without debug code on an Intel i7-920, 2,7Ghz):
- 95微秒为code
- 当一切除了现在注释掉的语句注释掉5.609毫秒(
Bevel.Left:=
) - 0.056毫秒,当所有code是由
替换X:=时间* GPF.PpM格MIDI_Resolution;
如图所示
- 95 microseconds for the code as shown
- 5.609 milliseconds when all is commented out except for the now commented out statement (
Bevel.Left :=
) - 0.056 microseconds when all code is replaced by
x := time * GPF.PpM div MIDI_Resolution;
只是围绕一个锥搬家费用60倍,CPU只是作为一个绘图画布。这让我感到惊讶。测量1的结果非常发声(还有比这只是更会),但2和3未。我需要某种形式的反馈给用户什么的球员现在正在处理,一些线路在钢琴卷是接受的方式。在我的上房减少了定时事件循环的CPU周期的追求,我有一些问题:
Just moving around a Bevel costs 60 times as much CPU as just drawing on a Canvas. That surprised me. The results of measurement 1 are very audible (there is more going on than just this), but 2 and 3 not. I need some form of feedback to the user as what the player now is processing, some sort of line over a piano roll is the accepted way. In my never ending quest of reducing CPU cycles in the timed-event loop I have some questions:
- 为什么围绕一个斜角的成本是多少时间? 动
- 有降低比上一个位图吸引更多的CPU周期的方式?
- 有图纸时减少闪烁的方式?
推荐答案
您将无法改变世界,也不VCL也不支持Windows。我怀疑你是问得多那些...
You won't be able to change the world, nor VCL nor Windows. I suspect you are asking to much to those...
恕我直言,你最好改变一点点你的架构:
IMHO you should better change a little bit your architecture:
- 声音处理应在一个(或多个)分隔线程(s)和不应该在所有链接到UI(例如不脱离其发送GDI消息);
- UI刷新应使用定时器与一个500毫秒的分辨率(半秒刷新听起来有足够的反应),而不是每次有变化。进行
也就是说,编曲不会刷新的用户界面,但用户界面将定期向音序器是什么其当前状态。这将是恕我直言更加顺畅。
That is, the sequencer won't refresh the UI, but the UI will ask periodically the sequencer what is its current status. This will be IMHO much smoother.
要回答你的问题的确切:
To answer your exact questions:
- 移动锥实际上是发送一些GDI消息,并且渲染将通过使用临时位图GDI堆栈(GDI32.DLL)进行;
- 尝试使用更小的位图,或者尝试使用Direct X的缓冲区映射;
- 尝试
DoubleBuffered:= TRUE
您TForm.OnCreate事件,或者使用专用的组件(TPaintBox
)与整个成分含量的全球位图,用类似的东西为消息WM_ERASEBKGND
。
- "Moving a bevel" is in fact sending several GDI messages, and the rendering will be made by the GDI stack (gdi32.dll) using a temporary bitmap;
- Try to use a smaller bitmap, or try using a Direct X buffer mapping;
- Try
DoubleBuffered := true
on your TForm.OnCreate event, or use a dedicated component (TPaintBox
) with a global bitmap for the whole component content, with something like that for the messageWM_ERASEBKGND
.
有些code:
procedure TMyPaintBox.WMEraseBkgnd(var Message: TWmEraseBkgnd);
begin
Message.Result := 1; // no erasing is necessary after this method call
end;
这篇关于减少VCL花费的CPU时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!