Closed samschott closed 3 years ago
The short answer is "I don't know". I definitely can't suggest an implementation that would be faster.
My best guess would be that something in the construction process is populating a cache; if the slowdown is happening on every call, then there might be a cache that should be preserved but isn't, or something that is triggering a cache population that could be invoked directly.
The only approach to resolving this I can suggest at this point is to profile the code to determine where exactly the slowdown is occurring.
It also might be better to migrate this issue to the rubicon-objc repository (or, at least, open a related issue), as the fix here is unlikely to be TogaIconView specific.
Ok, I will have a look at the rubicon-objc internals and see what I can find. In the meantime, I have opened PR #1031 which prevents all cells from being initialised when populating the table: The code to determine the row height now avoids initialising the cells in each row that it looks at. This already speeds up populating large tables.
After a bit of digging, there seem to be two possibly unrelated issues - and I am not sure where they come from:
init
of the super-class is very slow.alloc().init()
of a simple ObjC class takes about 600 μs. The setup method of TogaIconView
initialises text and icon fields as well as six constraints, leading to a total of 5 ms.Especially the second point is concerning when building more complex user interfaces. PyObjc for example only takes 10 - 15 μs to create each class instance.
I'll file corresponding reports directly with rubicon-objc.
Considering the performance improvements in the upcoming rubicon-objc release, this issue can probably be closed.
Closing on @SamSchott's recommendation. I'll put an updated Rubicon release on my todo list.
Describe the bug
TogaIconView.alloc().init()
takes about 15 ms. This is very slow for initialising a class and compares to about 600 μs for initialising the parent classNSTableCellView.alloc().init()
. This results in horrible performance when showing large tables. Half of the time, about 7 ms, is spent when calling the paren't initialiser:https://github.com/beeware/toga/blob/86afe6bf94d26e5d58b02a22ed4633622f4110b2/src/cocoa/toga_cocoa/widgets/internal/cells.py#L40-L43
The other half is spent when running the
setup
code.I suspect that the bad performance has to do with the conversions between Python and Objc types and that the same code in Objc would be faster by orders of magnitude.
Is this actually the recommended when of overriding the parent's
init
function? Or is there an alternative with better performance which is preferred? I wrote the original code following the discussion in https://github.com/beeware/rubicon-objc/issues/32 but maybe that advise is outdated.Edit: To be fair, the view-based rewrites of
toga_cocoa.Tree
andtoga_cocoa.Table
still provide significant performance improvements over the old cell-based implementations.Environment: