Am 07.07.2010, 23:30 Uhr, schrieb shi <[email protected]>:

>
>> > Just sending all those events is what takes up such a long time.
>
> Hello list,
>
> FC2 is really great and easy to use for my purpose,
> but the speed issue when adding objects to the canvas
> is a showstopper. To keep a long story short I
> added 60000 objects to the canvas, went to the shop, got back home,
> and then killed the process.
>
> I'm curious to know if someone is actively looking at this issue?

I'd really like to make fc2 work even with big workloads. Most of the  
functionality required for this is already present. As I've stated in the  
past, I don't have any time to spend on this right now and the foreseeable  
future. Mainly because the summer of code '08 is long over by now and I  
don't have the time/money for fc2 at this time.

> I took a first look by stepping through the code in the debugger,
> but the meta class magic that happens when adding an object currently
> is not entirely clear to me, nor is it clear what could be the impact of
> somehow preventing all this magic from happening.

The biggest mistake I made for fc2 is this: I wanted to spare the user the  
calls to "Refresh" in all kinds of places. This requires fc2 to internally  
track all changes done to an object. This allows things like detecting if  
the changes are really in the view or not. If you are changing things  
outside of the view, the Refresh would not be called.
Detecting all attribute changes has two very big drawbacks:

1) It is extremely slow, because you have to override things like  
__setattr__. Calling __setattr__ hundreds of thousands of times is  
extremely slow in my benchmarks.
2) All attributes of classes like the looks, the models, the views,  
canvas, ... have to be able to send "I changed" events. I had the choice  
to make this either automatic or have a lot of redundant, error prone  
code. I chose the automatic way.

In hindsight, I'd just rip observables completely out and make the user  
call Refresh() where needed. Saves tens/hundred thousands of calls for  
detecting/sending/processing "change" events.

The second "meta" (although not meta classes) problem is this: The user  
can supply arbitrary data models to the canvas. E.g. you can get "House"  
objects directly out of your database and visualize them with a rectangle.  
There's not need to manually create Rectangles from the "House" objects.  
This way if somebody changes the coordinates of the House in your database  
you can see the change on the canvas without having to remove/re-add the  
rectangle belonging to the house.
Additionally fc2 allows you to write custom renderer back-ends. The  
gcrenderer is just an example implementation of a back-end. Making the  
rendering back-end independent required yet another layer.

So observables, arbitrary models and independent renderer back-ends  
complicated the implementation of the simple "draw objects on canvas"  
idea. If I had had more time, I'd refactored and made this easier for  
other people to work on.

In my tests this part was not really slow, I haven't tested with 60,000  
objects though. I did some small experiments when I added the r-tree c  
library support and cProfile mainly spent time executing the same  
functions many many times, most of them related to observables. So I think  
60,000 objects are handleable with refinements to the implementation (and  
provided most of the objects are not visible as looping over 60,000  
objects in python and rendering each individually will be non-interactive  
anyway).

> Would it make sense to try to extend the pubsub Publisher() so that it  
> can
> be instructed to temporarily suspend dispatching certain messages to its
> listeners? As a way to implement a "freeze" of some kind?

I think changing Publisher is not enough, you'd have to rip out  
observables completely.

Ripping out observables has another side-effect: Render-to-surface nodes  
use the "changed" events model to determine if they need to redraw  
themselves. This also needs to be signaled by the user. I'm not sure if  
observables also played a role in caching transform chains, but I don't  
think they did iirc.

Conclusion:

- If you have time to spend, rip out observables and then do a quick  
benchmark. This might take longer than you anticipate initially.
- If you want to make your project work right now, you might want to  
abandon FC2 and try a quick test with FC1 instead. Or use a completely  
different framework (like a 2d game engine which does all the looping in  
C).

-Matthias

P.S.: If you look into floatcanvas2.config there's a functon called  
"enableSpeedmode". This is a bit like ripping out observables, but it's  
just a quick hack and the benchmark still shows too many redundant  
function calls.
_______________________________________________
FloatCanvas mailing list
[email protected]
http://paulmcnett.com/cgi-bin/mailman/listinfo/floatcanvas

Reply via email to