WebCanvas update speed when canvas is already populated

I have rewritten a small section of my app concentrating around the invalidate paint event and attached it to feedback 38880 .
Its not perfect but it highlights the problem nicely.

If anyone has managed to speed this up please let me know how.

I have seen it suggested not to do calcs in loops etc in other threads but realistically a loop is exactly how your going to layout your canvas. My profiler suggests 17 ms to repaint but the thing hangs for at least 20 seconds even if you reduce the column count in the example by 1. This delay is simply unrealistic for any app.

Some more testing with the above mentioned example

#pragma backgroundtasks true

initial load 19ms
30 rows, 8 cols, 12 char string - 43765
30 rows, 8 cols, 12 char string (same grid but different text) - 36120

#pragma backgroundtasks false

initial load 20ms
30 rows, 8 cols, 12 char string - 42812
30 rows, 8 cols, 12 char string (same grid but different text) - 38464

Is this a realistic expectation for a developer?

I’m not sure it is applicable here, but I have written a very fast free WebCanvas for Xojo called ABXPlay. Especially the ABXPlayPrimitives demo could be of some use.


Thanks, will take a look

Chris - I downloaded and tested your Feedback project. With inputs of 8x30x12 (cols x rows x string length) it takes roughly 35 seconds to draw, comparable to what you’re seeing.

I copied your page to another project and changed it to use jCanvas in Web Custom Controls. jCanvas can be used as a vector surface, i.e. you can add “layers” which are individual drawn objects. You can then change a layer’s properties (position, size, color, text, etc.) without redrawing the entire canvas.

Using jCanvas layers it takes 5.5 seconds to setup the initial grid from scratch. But once it’s setup changing all the strings takes 1.5 seconds. Both times are with the 8x30x12 grid.

If I treat the jCanvas control as if it was a traditional Xojo canvas (there’s a wrapper class for this) then it seems to take about 4.5-5.5 seconds with your original paint code.

My toolkit isn’t free, so it’s certainly worth trying to find a work around for the built in canvas. And trying out Alain’s, which may be faster. I haven’t had the chance to play with his canvas yet.

But if neither option works, consider WCC. Using jCanvasLayer objects is a nice way to work when you have a complicated drawing or control where only parts of it need to be updated at any given time.

Basically I am trying to get a calendar view going.
Literally I could need as many as 8 cols by 97 rows (cols for days of the week and rows for max resolution of 15 mins over 24 hours).
I have tried containers, a little too slow unless you use 100 or so.
Canvas is just crap
listbox is zippy but has no real formatting options.

I cant believe the canvas is that slow its just crazy. First load its quick as. After that you have to wait a minute!
I need the speed of a listbox with the control of a canvas!

Daniel if your canvas was faster I would buy it in a heart beat but 5 seconds is just too long for only 30 rows. I really do appreciate the effort though.

I’ll take a look at that case and see if I can tell what’s going on.

I would appreciate that Greg, allot!

processor load goes to 30 % also, something is crunching numbers.

I just tried a workaround by drawing to a picture graphics and displaying it afterward in an ImageView. With on the same WebPage a WebCanvas and an Imagewell drawing the very same pattern, the canvas is much slower, but the resolution is much better.

Chris - I modified your project so that the following sequence occurs.

  • Click button.
  • Action event sets a new property “ClearCanvas” to TRUE; invalidates canvas; starts a new WebTimer in single mode with a 1ms delay.
  • Paint event fires; sees ClearCanvas=TRUE; uses FillRect to paint the canvas white; clears the property.
  • Timer event fires and invalidates the canvas again.
  • Paint event fires again; ClearCanvas is FALSE so your drawing code runs.

This is just for testing and is not how I would do this in production code…but the final time to redraw the grid is 5.7 seconds this way. This is 8x30x12.

8x97x12 takes 13.5 seconds.

I should note that for all times I’ve posted I’m using my iPhone stopwatch and not relying on the reported microseconds. Timing code in Xojo cannot account for JavaScript transmission and execution.

Simply adding code to FillRect the entire canvas before drawing anything else does not work. (And your code does this any way.) The canvas has to be cleared during one Paint event, then redrawn in another. I think it’s safe to say that the WebCanvas diff engine, which normally helps, is failing for some reason in this case.

But if 5 seconds is not fast enough…and 13 certainly is not…then you probably need to look to a custom control with client side JavaScript that renders the grid you want.

You mentioned that WebListBox is fast but has limited formatting options. WebListBoxTD in Web Custom Controls lets you use whatever HTML you want in the cells. So that may be an option for you. But before you spend $$$ on my kit I would want to discuss and build a test case to know for certain if it can do everything you need with acceptable performance. Let me know if you want to explore that option.

I am currently experimenting with creating a html table and loading that into the html viewer.
I will get back to you Daniel.

Just for sports I’ve recreated the grid demo with ABXPlay. As it’s not really made for this, it has some limitations, but I may find some ways around it if I find the time (like writing a reset of the ABXPlay object when the grid changes size.

As for now, this is how it works:

  1. Start the project
  2. Initial load of the page will take some time, as Xojo needs to move my objects JavaScript to the browser. Just wait until the Button enables.
  3. Fill in your values and press the button (Columns and Rows editfields will be disabled)
  4. Press the button to fill the grid with other values

If you want to change the Columns/Rows, just refresh the page in your browser.

The idea wouldn’t be to bad if grids could be written with ABXPlay, because it could have lots of fun stuff like dragging cells around or animating them as everything (text, drawing, etc) is an object in ABXPlay that can be manipulated.

I’ve been thinking for a while to make ABXPlay open source, so maybe time to actually do it :slight_smile:

Source code download: http://gorgeousapps.com/ABXPlayGrid.zip


I truly appreciate the effort but I most definitely need to be able to change things like the number of columns and rows. The example I posted was just that and is far different from the complexities my app incorporates. Also Chrome throws some weird bug message which does not affect anything if ignored. Clients will freak out seeing that.

No worries, as I wrote, just for sports

It would be nice if you could give me an example of the errors you get in Chrome though, as I’m testing it also in Chrome and don’t get errors.

And maybe the Xojo devs get some ideas from it how to speed up the Xojo webcanvas… :wink:

I can confirm embedding a container with a canvas each time I need to “refresh” the canvas is light years quicker - we are taking a factor of at least 1000 times.

below, thisCC is a property. As you can see it is destroyed everytime I refresh. The paint event is automatically drawn when shown so I dont need to bother with that.

if thisCC <> nil then thisCC.Close dim cc as new ContainerControl2 thisCC = cc thisCC.EmbedWithin(self, 300, 5, 900, 800)

The worst result I got was - ContainerControl2.Canvas1.Paint 1 139.0000 139.0000 this was 8 columns, 97 rows and 12 characters of random. It actually took just over 11 seconds to display which is again unacceptable, despite the profiler results. If paint truly is taking 139ms is it the diff algo taking up the rest of the time? Is it possible to have a flag that turns it off or some config options so we can optimise it to our needs?

If the built in control is anything like mine, Paint is merely preparing JavaScript to be sent to the client. For the built in control that JavaScript has to go through the diff engine on the server side to generate the final JavaScript package. Then for any control it is compressed, transmitted, decompressed, and executed client side.

It is certainly possible for a long delay in a web app to be due entirely to transmission and/or client side execution. But I would guess that the culprit is the diff engine in this case.

I’ve been looking more closely at this use case with the jCanvas control and I’m finding a large penalty for my use of JSONItem.ToString. It looks like 3.5s out of the total 5.5s (measured until client side completion) is actually JSONItem.ToString executing on the server side. (It gets called for each layer.) In theory if I could eliminate that it would yield a 2s grid setup time with grid updates well below 1s.

Not sure what I’m going to do with that yet, if anything, for the very next release. But it is intriguing.

Glad I gave you food for thought Daniel!

For now I need to either publish my app with delays or restrict the data I show.
Neither of those makes me feel warm and fuzzy and clients will not accept it.

1 second updates would be the top limit for me regardless of complexity in the paint algorithm.

I am seriously looking at alternatives as this is a huge show stopper.

I am also interested in transmission latency. I may compile the app and run it in AWS in the states or somewhere far away and see what happens.

I wonder if the delay is caused by the comparo algorithm running inside the loops?
I have no idea as an end user but something is making it hang.