4 ms·
The "modernness" in Nana comes at a heavy cost : callbacks are based on std::function, which means that adding a callback - e.g. as in their front page : b
by jcelerier 8y ago
The "modernness" in Nana comes at a heavy cost : callbacks are based on std::function, which means that adding a callback - e.g. as in their front page :
btn.events().click([&fm]{
fm.close();
});
will do a dynamic allocation, and create an indirection, since std::function does type erasure (so you get a vtable, etc...).
Qt may look less modern, but the cost of doing a `connect` there is far smaller especially if you connect to a member function.
- dearrifling 8y agostd::function implementations typically have small buffer optimization, a lambda capturing a single reference will most likely fit in there. But yes, it's quite heavyweight in general.
- radarsat1 8y agoFor a high-speed callback that might not matter but is the potential slowdown of a few microseconds for the extra indirection really a problem for reacting to button clicks?
- zarkov99 8y agoHard to see how that is a real problem. For one std::function implementations usually do small obj optimization, so if all you are capturing is a pointer there is typically no allocation. Furthermore, this a setup cost, so typically only paid once, and it is a UI, so there is a human in the loop anyway, which enormously increases the performance tolerances.
- antoinevg 8y agoOh ffs, have you actually calculated this "cost" on a CPU made after 1985?
- eps 8y agoWelcome to the Kingdom of Electron, where RAM is aplenty and CPU cycles are puny noise down the line.
- projektfu 8y agoYou're looking in the wrong place for performance improvements. These are not the inner loop. They're not even the outer loop.
- eps 8y agoThese can be in fast path, depends on the code, but that's not the point. Coming from embedded development, the amount of short-lived heap allocations that are so conveniently swiped under the carpet with C++ is ridiculous. Even with something like slab allocators and extremely cheap allocs, there are always cases when alloc-free cycles fall on the edge of slab and become very expensive. The less is allocated during the run-time the better. When these are combined across the whole codebase, optimizing them away _does_ result in a noticeable speed increase and makes the whole thing behave more predictably. Regardless of their perceived per-call cost.
- antoinevg 8y agoTo contextualise, my comment absolutely assumed a modern desktop target. I obviously would not be using this (or anyone else's higher level framework!) if I was targeting an embedded platform.
- frutiger 8y agoChromium is to blame not Electron. Electron is “just” Chromium + Node.
- 0815test 8y agoWeb and ECMAscript standards are to blame not Chromium. Chromium and Node are "just" implementation work, it's not like Firefox is that much better either!
- frutiger 8y agoHa, I totally agree. Actually if we’re being honest, it’s the programmers that are to blame. But the downvotes indicate the cognitive dissonance here. It’s still fashionable to hate on Electron.
- jcelerier 8y agoThere's a lot of costs which all sum up: - binary size increase (e.g look at that : https://gcc.godbolt.org/z/xre7cp https://gcc.godbolt.org/z/xre7cp) - more symbols (I guess you never hit the per-object file symbol limit on windows, even with /BIGOBJ - when you do the only thing left is despair). - most callbacks will have to copy a kind of `this` pointer so the size of your objects increase and they stop fitting into cache lines - when you have "normal" inheritance, the vtable of your parent object is generally already in your cache, while here there will be one vtable per-object (and no, the vtables aren't optimized to be part of the object itself so you still get that indirection even with SBO). so goodbye memory coherency. I've been working on my own callback implementation with an inlined vtable which allowed me to grasp sometimes more than 30% perf improvement vs std::function, in callback-heavy code : https://github.com/jcelerier/smallfunction/blob/master/smallfun/include/smallfun.hpp#L29 https://github.com/jcelerier/smallfunction/blob/master/small...
- 0db532a0 8y agoHow many callbacks do you plan to be adding/calling per second?
- jcelerier 8y agoadding ? not much. calling ? I've worked in apps where there are multiple thousands callback firing per second - and you've got a 8 ms deadline to show data on screen.
- 0db532a0 8y agoMaybe I jumped the gun. I’m not an expert on GUI programming. In what case do thousands of GUI callbacks need to be called in one second? I would be interested to know.
- stargrazer 8y agoSo... other than using std::function and other than something in Qt, what would be a more efficient C++[11,17] native way of doing a callback?
- Elv13 8y agoGoing from "more efficient" to "most". That would be the assembly `asm("JMP *%eax")` instruction or something like it.
- int_19h 8y agoThat would be the assembly way of doing a callback, not a C++ way.
- jcelerier 8y agohttps://stackoverflow.com/questions/4298408/5-years-later-is-there-something-better-than-the-fastest-possible-c-delegate https://stackoverflow.com/questions/4298408/5-years-later-is... ; you loose some flexibility though.
- CamperBob2 8y agoAny modern OS has tons more overhead than that in its own GUI/GDI layer. Not (much of) an issue.
- pjmlp 8y agoThe typical premature optimization worry that afflicts so many in the community before writing a single line of code. Unless the profiler marks that code as reason to worry about, I wouldn't spend one second thinking about it.
- jcelerier 8y agowell, I am having this comment because I had to spend months optimizing some UIs which updated thousands of elements per second with this kind of mechanism - needless to say, it doesn't scale, especially when your average user has a core 2 duo.
- jstimpfle 8y agoCallbacks are often not the best approach. How about "inverting" the control by having a function which first collects all the elements to act on and then acts on them? This should prevent problems with cache misses since you perform only one kind of thing (on all elements) at a time. Where this kind of reordering is possible. (The callback approach is OOP I would say. And as always, OOP prevents us from seeing the better way to structure processing).
- jcelerier 8y agoproblems happen as soon as the elements you want to display aren't known at compile time and can't be stored in a nice, data-oriented approach, but instead come from various plug-ins that the user can download and put as DLLs in the app's folder.
- qPCR4vir 8y agoCould you explain that more? “a heavy cost : callbacks are based on std::function (will do a dynamic allocation, and create an indirection)” v.s. “Qt the cost of doing a `connect` is far smaller” ?? How Qt achieves that using string comparisons at run time? https://doc.qt.io/qt-5/signalsandslots-syntaxes.html https://doc.qt.io/qt-5/signalsandslots-syntaxes.html