Hey,

Callback arrays was an idea that was introduced a while back to save 
memory. The idea came from the observation that in many cases we add a 
few callbacks together to every object of the same type. For example, 
for an elm widget, we may add "move, resize, hidden, mouse_down, 
mouse_up" so instead of manually adding all of them separately and have 
eo allocate memory for each (and a separate private data pointer for 
each) we would just create a static array and pass that.
This leads (at least in theory) to quite significant savings in memory. 
I haven't actually tested the change, as I didn't do it, Cedric, do you 
have some numbers to share?

However, while they provide a nice memory improvement, they have been 
hampering many optimisation strategies that would make callback 
invocation significantly faster. Furthermore, maybe (not sure), we can 
automatically de-duplicate event lists internally (more on that in a 
moment). With that being said, there is a way we can maybe keep array 
callbacks with some limitations.

I discussed my ideas with Carsten on IRC and I believe we have reached 
something that would be significantly faster and better.

Assuming callback arrays are no more:
First of all we will change the internal callbacks structure from a list 
to array. The array will be sorted based on the address of the event 
structure first, and priority second. The array will only include the 
pointer to the callback structure, nothing else. All of the rest of the 
information needed will be stored in an array of the same size and the 
same order.
This means that we will now be able to walk the array and stop once the 
address of the event we are looking for is higher than the address of 
the address of the current event. Meaning we will walk only 50% of the 
array on average, and the array itself will most likely be in the same 
cache line. After we find the correct one, we will also fetch the rest 
of the data based on the index. This will lead to blazing fast 
iterations of callbacks without the need to optimise at all.

We can also store a pointer to the array in a hash table with the key 
being some sort of a hash of the array in order to do some deduplication 
afterwards (point to the same arrays, but obviously different private 
data, so that would still be duplicated) if we feel it's needed. It 
probably won't save as much though and will have some running costs.

The last idea is to keep callback arrays, but kind of limit their scope. 
The problem (or at least one of them) is that callback arrays support 
setting a priority which means calling them needs to be in between the 
calls to normal callbacks. This adds a lot of complexity (this is a very 
hot path, even a simple if is complexity, but this adds more). If we 
define that all callback arrays are always the lowest priority (called 
last), which in practice will have almost zero impact if at all, we can 
just keep them, and just call them after we do the normal callback calls 
(if they exist). We can even optimise further by not making the arrays 
constant, and thus letting us sort them and then run the same algorithm 
mentioned above for searching. This is probably the most acceptable 
compromise, though I'm not sure if it'll block any future optimisation 
attempts that I'm not able to foresee.


I'm not a huge fan of callback arrays, but if they do save the memory 
they claim to be saving, I see no problem with keeping a more limited 
version of them that let us optimise everything in the manner described 
above.

Thoughts? Or should I just go on with implementing and benchmarking this 
change?

-- 
Tom.

------------------------------------------------------------------------------
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to