New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
toolkit-agnostic Core->GUI Communication (Draft B) #1765
base: master
Are you sure you want to change the base?
Conversation
the BASE rectangle can be made invisible instead of using the same color as the RECT
TODO: iolets
absolute positioning only makes sense on a given canvas
4902b12
to
16dbd32
Compare
since we are now reading the actual position back from the canvas, the zoom is already applied, and we must not re-apply it.
and send an extra message for object-specific configurations. LATER move the common code into g_all_guis.c
its not used
rather than using the background color. and rename to activation proc from 'flash' to 'activate' (it's a re-usable name for all iemguis)
yes. from Pd-core's POV, there is somewhat less work to do, but the GUI now has to do some more lifting (and there's a couple of indirections built into my current system, e.g. the command dispatcher). now I dearly love the command dispatcher (e.g. allowing us to use a single |
no more multi-value values
so time for some profiling. reference
21ms for 768 objects is not that bad. this implementation (with some hacks)
the "no-label" and "no-select" options are only here for comparision. in the end, we cannot just omit them (although there is room for optimization. in any case: text is obviously expensive) there are two obvious ways to optimize the current implementation:
bypassing the widgetbehavior dispatcher
using explicit tags
using explicit tags and bypassing the widgetbehavior dispatcher
as can be seen there's plenty of potential to optimize, but even in the best case (condense the configuration into the constructor; explicit tags; bypassing the proc dispatcher), we are still about 10 times slower than what is currently happening... |
Hey, these are pretty bad news... Maybe there's a possibility to continue in this way (which is to make pd core agnostic from the GUI toolkit, while keeping TclTk at first, before people can try implementing the GUI with another toolkit): how about writing a temporary C (or C++...) gateway between the core and the GUI, that would do all the widget abstraction layer, and would send only digested commands to TclTk, which would only have to do the final display job? Then we should expect similar performance as the "reference" Pd. Maybe we would need to run the gateway in a secondary thread, to avoid impacting the real-time requirements with GUI-related processing and dynamic memory allocation. Thanks a lot for all your time on this anyway! |
I tried to use the Sample output for that function
Full output: steps to reproduceUse this Pd patch (32*24 floatatoms without iolets plus a loadbang-delayed-message): Apply these changes:
Note: the Wish.app 8.6 that is installed in my macos didn't have the |
I notice here on macos that if I remove the
from the bottom of |
@Ant1r just for the record, i don't think all is lost. it was pretty easy sailing so far, but now the sea is getting rougher. i'm sure we will come up with some acceptable solution. @giuliomoro thanks for the additional tests. i have as for i've also completely disabled the call to |
it's just distracting code...let's get the core working first (and faster)
It looks like we cannot patch second inlets/outlets in this branch. This is because in
|
Here's something we've been working on for a few months: a web interface to Pd, which leverages the refactored communication protocol of this branch: https://github.com/BelaPlatform/pure-data-web-GUI It comprises of three components:
For now, you can try it out with docker following the instructions included in the repo. The easiest way is to run it with the Pd it comes with (which is run inside docker and thus doesn't have audio/MIDI I/O capabilities), but you can easily connect it to your own Pd server instance (assuming it comes from this branch with giuliomoro@8088029). It is by no mean complete or perfect, but I hope it shows that there is a tcl-tk-compatible, non-tcl-tk future possible for Pd. It even allows (well, with a lot of effort on the user side, but very little effort was put into it from the dev side) to patch on a touchscreen. Feedback welcome. Also, @umlaeute wondering what you think the next steps for this branch should be. We would be happy to contribute time and effort to it if needed, but need your guidance to put the effort where it's most needed. |
that's a good question. i think the benchmark is the current implementation: the performance of this rewrite must about the same (or faster obviously). this most likely means that the API will need to be a little less abstract (i guess the part that eats most resources is the iolet/connection thingy. so we probably have to ditch the idea for now, that the GUI can handle these on its own). i also have the feeling that the proc calls (and proc calls from these) add overhead, which shouldn't be there (afaik,Tcl byte-compiles procs, which should make calling a proc that calls multiple TclTk commands faster than calling those commands manually; but it seems this is not the case here) |
Optimization rule nr. 1: measure, measure, measure = run a profiler on the core and GUI process to find the actual hotspots. @umlaeute Do you have a test patch that exemplifies the performance problems?
Yes, this seems really strange to me. I would also expect performance to be better, since we send fewer messages to the GUI. We have to profile to find the actual problem. |
i guess that would be #1765 (comment) |
Thanks, will give it a try. One thing that came to my mind: I would be useful if there was a way to designate GUI transactions. Currently, we send lots of individual drawing commands, even if they just form one big operation (e.g. redrawing a canvas). If we could (optionally) wrap such commands in some kind of "begin" and "end" messages, this would enable huge optimization opportunities for the GUI backend, such as batching requests, temporarily disabling redrawing, etc. For example, in
This is a pretty common pattern. Two examples that spring to my mind: |
To expand on the previous post: In naive canvas implementations, every change to the canvas may trigger a full redraw. (I think that Tk belongs to this category.) If you issue many such commands in a row, every command will implicitly repeat all previous commands, leading to quadratic complexity. Theoretically, we could patch the Tk library and add commands to temporarily disable any redrawing. Together with Now, imagine a less naive implementation where a command does not immediately trigger a redraw, but rather schedules a redraw event. Even in this case, Finally, the core communicates with the GUI over a TCP socket; although commands are sent consecutively, they might arrive with delays and consequently get scattered over several event loop ticks, again leading to redundant redraws. |
that's really just one example (the "Steinway"). i'm not opposed though... |
Well, you can really find this pattern everywhere: database transactions, builder pattern, OSC bundles, openGL (
+1 |
Here's another example from Pd itself: |
Just found a bug on this branch: load a patch with a ticked checkbox and it won't show the checkmark upon loading. As expected, the state is actually stored, so you need to click on it twice to see the tick appear. Example patch:
|
I think this is what is described in the top post under the heading "regression" |
My understanding* is that tcl/tk always defers drawing. So maybe it's just a matter of queueing messages received after * hint that contributed to this understanding: the update man page says
|
Ok, so it rather falls into the second category described in #1765 (comment)
Yes, that's what I was thinking. |
Maybe doing all the command parsing and string handling to draw on the Tcl side is simply slower because the original implementation just sent the command directly to Tk as opposed to additional Tcl proc layers. I feel like that could be a bottleneck and could use some finer-grained profiling. |
If calling procs and string handling is the slowdown on the Tcl/TK side, one approach could be to write a Tcl plugin to do it in C then send it back to Tk. |
i always assume that the tcl guys know what they are doing (language wise): after all interpreting strings is at the core of the language itself, and afaik there's even some jit-compiler hidden somewhere. maybe we are bypassing this when reading the commands from the socket. |
Yeah, I did too, otherwise it never would have been usable on the original hardware it was developed for in the 90s. The only thing I can think of is some sort of memory allocation on the fly, but that shouldn't be anything we have to deal with directly. Strange. |
this is just another draft, in addition to #1763 to resolve #1695
i started with a simple GUI-object (namely
cnv
, as it doesn't have any iolets), and implemented:cnv
that lives entirely on the GUI sideinternal state
so far this adds a bit of state to the GUI, namely:
cnv caches it's main color on the GUI, so selecting an object just tells the object that it is now selected (or not), and we don't have to send along the selected/unselected color(EDIT: actually in this case we can just make the 'unselected' rectangle indicator invisible)state of the draft
very early, apparently.
so early, that it is likely to break unrelated functionality (e.g. i started replacing parts of the common iemgui C-side implementation, without worrying whether this works for all iemgui objects so far...)
regressions