Re: Drawing thread not getting enough time from scheduler?

Thanks for looking at the code, Mario. I made those modifications (to
my prototype as well as my game library, where I had been re-using a
DC but had not been caching pens).

It did speed things up a bit, but it still runs many times faster (55
seconds vs. 5 seconds) if I join the animation thread.

thread = Thread.new do
  black_pen = Wx::Pen.new(Wx::Colour.new(0, 0, 0), 0)
  green_pen = Wx::Pen.new(Wx::Colour.new(128, 255, 128), 3)
  300.times do |i|
    buffer.draw do |surface|
      #Clear screen.
      surface.pen = black_pen
      surface.brush = Wx::BLACK_BRUSH
      surface.draw_rectangle(0, 0, 300, 300)
      #Draw lines.
      30.times do |j|
        x = i + j
        surface.pen = green_pen
        surface.pen.cap = Wx::CAP_ROUND
        surface.draw_line(x, 0, x+100, 100)
      end
    end
    #Update screen.
    update_window(window, buffer)
  end
end
#Makes GUI unresponsive if uncommented.
# thread.join

Any idea how I can get the thread scheduler to devote a bit more time
to animation, without completely freezing the GUI?

-Jay McGavren
http://jay.mcgavren.com/zyps

Mario S. wrote:

Well, one optimization that I can see just by skimming the code, is that
your creating a DC Buffer each time you loop to draw a line. The grabbing
of a DC weither it’s an On-Screen Control, or an Off Screen Bitmap.

If you would also notice, I’m not constantly re-creating the Wx::Pen
either. Since it’s created once, and your using the same colour, and size
for the Pen, there’s no reason to be re-creating it for each and every line
you draw.

Jay McGavren wrote:

It did speed things up a bit, but it still runs many times faster (55
seconds vs. 5 seconds) if I join the animation thread.

Any idea how I can get the thread scheduler to devote a bit more time
to animation, without completely freezing the GUI?
Just had a chance to try your code. For me on OS X it doesn’t work at
all if thread.join is called, but runs pretty smoothly (about 8s total)
otherwise. At some level you’ll also be caught by the granularity of
Ruby’s thread time slices (10ms IIRC), and garbage collection, which is
taking up to 9ms tracking wxRuby objects alone in your example.

I see a couple of further potential optimisations in your code which
improve smoothness for me:

  • Take the calls to surface.pen= and surface.pen.cap= out of the
    30.times loop.
  • See whether the drawing could be more efficiently done with a single
    draw_polygon (which acccepts an Array of Wx::Points)

Another untested possibility to improve perceived smoothness might be to
drive the animation from a Wx::Timer. Have it run at regular intervals,
calling window.refresh to invalidate the window, then copy from the
bitmap inside an evt_paint handler.

Let us know how it goes…

cheers
alex