Page 1 of 1

Slow StartDrawing

Posted: Tue Nov 15, 2011 12:14 am
by Polo
Hello,

Here's a code to point out something rather annoying:

Code: Select all

If OpenWindow(0, 0, 0, 460, 400, "CanvasGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  canvas = CanvasGadget(#PB_Any  , 10, 10, 380, 380, #PB_Canvas_ClipMouse)
  
  t=ElapsedMilliseconds()
  
  For i = 0 To 1000
    StartDrawing(CanvasOutput(canvas))
    StopDrawing()
  Next
  
  t2 = ElapsedMilliseconds() - t
  MessageRequester("",Str(t2))
  
  Repeat
    Event = WaitWindowEvent()
    
    
  Until Event = #PB_Event_CloseWindow

EndIf
It doesn't do anything of course, however the start/end drawing takes 1500 milliseconds on my Mac. If i swap to ImageOutput with an image, it then takes 300 milliseconds.

It makes no sense to do 1000 Start/EndDrawing here, but my code is using several Start/endrawing to get the text width and lenght, and is very slow when parsing 1000 lines because of what I shown before.

Why is it taking 1.5 seconds to do nothing? Why is it slower than when using an image?

Re: Slow StartDrawing

Posted: Tue Nov 15, 2011 3:09 am
by Demivec
Polo wrote:It doesn't do anything of course, however the start/end drawing takes 1500 milliseconds on my Mac. If i swap to ImageOutput with an image, it then takes 300 milliseconds.
It is my understanding that the CanvasGadget is double buffered. The ImageGagdet isn't double-buffered and so it makes sense that it would be faster.
Polo wrote:It makes no sense to do 1000 Start/EndDrawing here, but my code is using several Start/endrawing to get the text width and lenght, and is very slow when parsing 1000 lines because of what I shown before.
Whenever possible it is wise to combine operations that require Start/EndDrawing together so that any unnecessary delays are prevented.

Here's a link that may prove useful.

Re: Slow StartDrawing

Posted: Tue Nov 15, 2011 7:38 am
by Danilo

Code: Select all

If OpenWindow(0, 0, 0, 460, 400, "CanvasGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  canvas = CanvasGadget(#PB_Any  , 10, 10, 380, 380, #PB_Canvas_ClipMouse)
 
  Dim sizes(1000)

  t=ElapsedMilliseconds()
 
  If StartDrawing(CanvasOutput(canvas))
      For i = 0 To 1000
        sizes(i) = TextWidth(Space(i)+"abcdfefhhhkhkh")
      Next
      StopDrawing()
  EndIf

  t2 = ElapsedMilliseconds() - t
  MessageRequester("",Str(t2))
 
  Repeat
    Event = WaitWindowEvent()
   
   
  Until Event = #PB_Event_CloseWindow

EndIf

Re: Slow StartDrawing

Posted: Tue Nov 15, 2011 9:33 am
by Polo
Demivec wrote:
Polo wrote:It doesn't do anything of course, however the start/end drawing takes 1500 milliseconds on my Mac. If i swap to ImageOutput with an image, it then takes 300 milliseconds.
It is my understanding that the CanvasGadget is double buffered. The ImageGagdet isn't double-buffered and so it makes sense that it would be faster.
Drawing to an image doesn't use the ImageGadget :)
Can't use your code Danilo, if I'm calling StartDrawing many times it means it can't really be avoided! Although using a 1x1 image did the trick, my code is much faster now.

Re: Slow StartDrawing

Posted: Tue Nov 15, 2011 12:16 pm
by Perkin
@Polo, - don't know whether it would be faster or not - can you just create an array of sizes for each individual character, which you fill in an initialising procedure, then when you need the width of a specific string, simply loop through each character and add the saved widths together?

You then shouldn't need all the StartDrawing/StopDrawing

EDIT: you should be able to speed this up as well.

Code: Select all

If OpenWindow(0, 0, 0, 460, 400, "CanvasGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  canvas = CanvasGadget(#PB_Any  , 10, 10, 380, 380, #PB_Canvas_ClipMouse)
  
  Dim SWid.l(255)
  If StartDrawing(CanvasOutput(canvas))
    For i = 32 To 127
      SWid(i) = TextWidth(Chr(i))
    Next
    StopDrawing()
  EndIf
  
  t=ElapsedMilliseconds()
  
  For i = 0 To 1000
    dum.s=Space(i)+"abcdfefhhhkhkh"
    res.l=0
    For j=0 To Len(dum)-1
      res+SWid(PeekC(@dum+j))
    Next
  Next
  
  t2 = ElapsedMilliseconds() - t
  MessageRequester("",Str(t2))
  
  Repeat
    Event = WaitWindowEvent()
  Until Event = #PB_Event_CloseWindow
  
EndIf

Re: Slow StartDrawing

Posted: Tue Nov 15, 2011 12:51 pm
by Perkin
As long as the text you need the width of is ASCII chars 32-127 then this is miles quicker,
change the timed loop to this

Code: Select all

  For i = 0 To 1000
    dum.s=Space(i)+"abcdfefhhhkhkh"
    res.l=0
    For j=32 To 127
      res+(CountString(dum,Chr(j))*SWid(j))
    Next
  Next

Re: Slow StartDrawing

Posted: Tue Nov 15, 2011 12:54 pm
by Polo
Well I'm using several fonts, with several sizes, and several attributes. Not sure I wanna store the data for everything....!

Re: Slow StartDrawing

Posted: Tue Nov 15, 2011 12:55 pm
by Perkin
Ah well now, that makes a difference.

Re: Slow StartDrawing

Posted: Tue Nov 15, 2011 1:08 pm
by Polo
Plus Textwidth("abcdef") will not necessarily returns the same as Textwidth("a")+Textwidth("b") especially with an Italic font, due to a Purebasic bug.
Anyway, using an ImageOutput is quite fast so I'm using that for now :)

Re: Slow StartDrawing

Posted: Tue Nov 15, 2011 5:15 pm
by Trond
I think the canvas output is slow because on every StopDrawing() it tries to update the display. I'm just guessing here.

Re: Slow StartDrawing

Posted: Tue Nov 15, 2011 5:38 pm
by Polo
Trond wrote:I think the canvas output is slow because on every StopDrawing() it tries to update the display. I'm just guessing here.
You're probably right, it'd explain everything.

Re: Slow StartDrawing

Posted: Tue Nov 15, 2011 7:55 pm
by idle
I think it's because it's preserving the alpha channel in it's drawing routine
which slows it down, you'd be better off doing all your internal drawing into an image
and then draw that to the canvas when it's done.