Pergunta

I'm currently trying to polish my application and improve it's performance. Basically, it's an advanced Graph- class. It draws a few lines and refreshes them.

After fixing a few slow points, I wanted to benchmark my result. My drawing was stuck at ~65 FPS (which is perfect but I'm benchmarking). I Invalidate my object in a timer (set to 1 ms) and redraw my stuff using the protected override void OnPaint -"way".

After that, I put the Invalidate() into the protected override void OnPaint. The FPS was set to a few thousand afterwards. But using that method will result in an empty screen.

My question is: Is that issue done on purpose? That would make sense as anything higher than your screen refreshrate is wasted power. But I'd like to disable that "lock" for my benchmarking.

Sample code:

//Timer to refresh
private void timer1_Tick(object sender, EventArgs e)
    {
        Invalidate();
    }

private DateTime date = DateTime.UtcNow;
    private long times = 0;
    protected override void OnPaint(PaintEventArgs e)
    {

        base.OnPaint(e);

        //Drawing
        e.Graphics.DrawLine(new Pen(Brushes.Black), 50, 50, Width - 100, Height - 100);

        //Required to tell me the framerate
        if ((DateTime.UtcNow - date).Seconds > 1)
        {
            date = DateTime.UtcNow;
            Debug.WriteLine(times);
            times = 0;
        }

        times++;
    }

Thanks

~Steve

Foi útil?

Solução

My drawing was stuck at ~65 FPS

Yes, that's normal. You are measuring the operating system's clock interrupt rate. It ticks 64 times per second on most Windows machines. A timer cannot go faster than that, the minimum useful value for the Interval property is 15. Setting it to 1 has no effect, it still only ticks once every 15.625 msec.

You can actually increase the interrupt rate and make the resolution of a timer better. You'd have to pinvoke timeBeginPeriod(). That's however pretty pointless, a human cannot observe the difference. The battery on your user's laptop however will, it drains a lot faster.

The smart thing to do here is to use a practical update rate. Human eyes go up to about 20 frames per second after which it just turns into a blur. Or looks smooth, depending on what kind of updating you are doing. Something that's taken advantage of in the movie theater, it updates at 24 fps. So practical Interval property values are a bit below a multiple of the expected clock interrupt rate. Which are 2 x 15.625 = 31 msec or 32 fps. And 3 x 15.625 = 46 msec or 21 fps. You don't want to arbitrarily make these numbers smaller, your program won't have consistent update rates on different machines if you do that.

You only need to optimize your code if your painting code cannot keep up with that rate. Nothing actually goes wrong on, say, a slow machine as long as you use a timer and don't try to force the rate up like you've been doing. The timer's Tick event will simply be delayed and your effective FPS will now be set by the speed of your painting code.

You avoid animation sequences taking longer on slow machines by calculating the actual elapsed time instead of relying on the frame number. Either from Environment.TickCount or DateTime.UtcNow, they update at the clock interrupt rate as well. Stopwatch is okay too, it is overkill. The animation will then take just as long as on a fast machine, it will just look coarser.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top