Skip to content
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

Performance #261

Open
tm1000 opened this issue Oct 11, 2024 · 14 comments
Open

Performance #261

tm1000 opened this issue Oct 11, 2024 · 14 comments
Labels
bug Something isn't working

Comments

@tm1000
Copy link
Contributor

tm1000 commented Oct 11, 2024

I've built this project on a raspberry-pi 4 with 8GB of ram. Loading a QLab file with 7 cue lists and 100 cues in each list it takes a long time to load.

Initially it seems to load the cues very quickly but then the styling of the cue "groups" seems to drag on for 20-30 minutes and the cpu spikes to 120%. I don't really expect amazing performance out of a raspi. However once this loading is complete cueview only takes about 10-20% of cpu. So the majority of the performance issues seem to be in the rendering portion of the QLab plugin

Have you given any thought to this project use vue or react. Perhaps this is just something that needs to be refined in the plugin itself

You also don't build for arm64-Linux but you have a build step for it in package so I suspect you were on the path of doing this

I think (my opinion) the raspi is a perfectly capable system to run this tool and something that could be the easiest way to utilize this for just "cue viewing"

@tm1000 tm1000 added the bug Something isn't working label Oct 11, 2024
@jwetzell
Copy link
Collaborator

It's unlikely that any sort of UI framework/library will be put into place here. I think exploring how to draw and render the cues in a more efficient would be best. For most of the plugins is what done in the easiest way to get it working which is not always optimal at scale. I can try and setup a QLab workspace that will cause it to choke and see what can be done about improving the speed of that.

Good note on the arm64 build as well, I will also look into how much of a lift that would be to add to list of releases.

@tm1000
Copy link
Contributor Author

tm1000 commented Oct 11, 2024

Hey @jwetzell

I can provide you this crazy workspace over Dropbox if you'd like. It's just a dance show so nothing copyrighted

As for the gui portion. All good. If/when I can contribute it's good to know what the vision/goal of the project is. In the end I doubt react/vue would make the execution any faster than native

Also when I get a few more cycles today I want to load the same show on my M3 Mac as I suspect it'll load much quicker.

I suppose after discussing this you'd say the goal would be to have it perform better on raspi systems if possible?

Of note. I did try to cross compile the Linux arm version on my Mac and it did not run correctly on the pi. So I had to just build it there. I don't know if you'd run into the same issue on GitHub's runners (also not sure if they have an arm64-Linux runner but I'd have to check)

@jwetzell
Copy link
Collaborator

I've got a workspace setup that seems to generally reproduce this. This probably is not unique to the QLab plugin so finding a good way to improve it would be beneficial across the board. The issue is usually with integrations where data is populated over time and not all at once (it takes multiple calls to populate all the data needed) for QLab the amount of message is at a minimum the number of cues and then add on a few more for other bits of data. Our general problem is that when data changes it usually means we need to redraw, but for plugins like this data can change fast when the connection is initially setup so device.draw() gets called a lot.

For a more intricate fix I think exploring some sort of virtual DOM concept might be more in line with what this really calls for as right now device.draw() is a generate body and replace what is there which is not exactly efficient to do really fast.

@tm1000
Copy link
Contributor Author

tm1000 commented Oct 11, 2024

@jwetzell heh "virtual dom"? So like react or vue

I kid

Kinda ;-)

In a case like this perhaps it is suited to at least try react/vuejs or something similar with the virtual dom concept.

Unless you want to write something from scratch yourself (https://medium.com/@deathmood/how-to-write-your-own-virtual-dom-ee74acc13060)

But if react and vuejs (+others) have already done the years of work to get theirs right...

Whatever it is it should be you deciding first. As for me an outside contributor/developer I'll go the direction of the project. :-)

@sparks-alec
Copy link
Contributor

To me, the major challenge here is how QLab informs clients of changes. If a root cue is moved, QLab tells you (via OSC) to fetch all the cues at root again. And to get all those cues, you need their children. Etc. You wind up having to re-draw the whole dang cue list pretty frequently.

I am not sure how much heuristics can be done to improve that without changes in QLab's OSC responses. The QLab remote app also struggles with very large cue lists.

I can ask the QLab folks to sit down with us and walk through exactly how they recommend an app like ours would communicate- I'd be curious to learn.

@sparks-alec
Copy link
Contributor

Also, as a person who primarily works in C++ and likes to do everything myself, I am pretty allergic to react and its relatives. I think they have made the web worse.

@tm1000
Copy link
Contributor Author

tm1000 commented Oct 12, 2024

The primary goal of react and others is the virtual dom. You could write your own here if so desired.

I think this could be tightened up to not call draw on every OSC change. Especially when you know you are getting the default list.

The issue here is truly that the browser is constantly rerendering its entire dom when only a single row is changing

To be fair this is already using a framework. That's electron. It's also using lodash as the template engine. Has another template engine been evaluated?

The most optimal format would be c++/rust/swift etc but you'd lose a lot of traction.

@jwetzell
Copy link
Collaborator

Currently, the draw function seems to just set the innerHTML of the body with the result of the template engine (not great..). The line that sets innerHTML makes up over 90% of the time spent in device.draw() (from the small testing I did).

When I've got some time I'll probably look into some libraries that might handle this DOM manipulation in a better way it doesn't even need to be virtual 🙃. I've explored swapping templating libraries just for the heck of it, there isn't much of anything crazy in these templates. But if it's just pure template -> HTML string not sure that helps anything (other than I don't like this templating language syntax).

@jwetzell
Copy link
Collaborator

I have started a branch qlab-fast-redraw-fix to explore some solutions that don't require changing up things a whole lot. Just basically avoid device.draw() as much as possible. If a new update comes in it basically postpones the draw which results in less overall draws (about two per cue list instead of one per cue list + one for every group cue in the workspace)

@tm1000
Copy link
Contributor Author

tm1000 commented Oct 16, 2024

@jwetzell those are interesting options for dom changes. Really I think anything could work or help.

With regards to qlab using it in a show with heavy projections causes it to just not respond constantly because of how much data is send back and rendered.

This is different than say EOS/ETC consoles (as @sparks-alec has stated). I am wondering if it might be better to keep state of qlab itself in memory of cue view and then using your work in the branch it might work better.

This application and https://github.com/jwetzell/showbridge are things I've wanted to write for years but never had enough motivation, since you'd done the majority of the work I hope I can find some time to contribute here and showbridge.

Side note @jwetzell why is showbridge not a part of stagehacks?

@jwetzell
Copy link
Collaborator

I'm not sure what is meant by "keep state ... in memory" we aren't writing state out anywhere so the state is built up in I assume memory (not sure where else it would be?). Have you tried that QLab branch, I understand it's not ideal and I guess if there is enough data coming in it could delay draw for too long. I did try those dom manipulation libraries with not much success in solving the speed problem. I think having to transform the result of the template (a string) into HTML elements for the dom patching every draw is also a pain point.

Thanks for the +1 on showbridge. It's pretty much something I whipped up in a couple months as an overreaction to a few messages from @sparks-alec regarding OSCulator 😂😂. There a few early decision I already kind of dislike (mainly the way protocols are handled) but that talk can continue over there. I'm not in charge of stagehacks, this is @sparks-alec doing 🤣!

@tm1000
Copy link
Contributor Author

tm1000 commented Oct 16, 2024

@jwetzell with regards to "keep state in memory" I've only briefly looked over the code. So let's ignore I said that!!!!

I'm going to compile the branch today on the pi and see how it goes. The issues I've noticed this far is when 10 cues are playing each cue has the active countdown and theres so much data coming in that eventually it just stops updating (but the app itself is still responding and the EOS screen continues to function). Hitting "reload app" fixes it. This goes along with keeping state in memory.. I realize from Alec that theres a TON of messages coming through, yet even when the qlab screen stops update the data symbol in the top right still functions so I know it's getting data.

I did try those dom manipulation libraries with not much success in solving the speed problem.

Ahh good to know!

I think having to transform the result of the template (a string) into HTML elements for the dom patching every draw is also a pain point.

Yes. I agree. Would it be more constructive in the qlab plugin itself to use javascript directly to update elements instead of re-rendering things. I am speaking this from my mind in the middle of tech week so forgive what I'm saying if it doesn't make sense.

Hey I have a license for OSCulator! and I recently tried to see if I could do midi to osc in it and I was disappointed to discover I couldnt do that

Ah good to know about what stagehacks is! If I find time to participate I'd love to be a part of this little group @sparks-alec. I've done theatre sound/projection design for 20 years and I also do computer programing as my full time (pays health insurance) job.

Edit looking through commit history I see @sparks-alec actually started this project. So there ya go. Nice job Alec! (really!)

@jwetzell
Copy link
Collaborator

Yes. I agree. Would it be more constructive in the qlab plugin itself to use javascript directly to update elements instead of re-rendering things. I am speaking this from my mind in the middle of tech week so forgive what I'm saying if it doesn't make sense.

Some of the plugins already do this, see the update function in the plugin's main.js. The QLab plugin does this for things like the playhead position, the hovering box with cue information and I think the time remaining stuff. So definitely possible to just directly manipulate.

@tm1000
Copy link
Contributor Author

tm1000 commented Oct 21, 2024

@jwetzell your fixes definitely helped. However the stage manager for this production asked we stop using cueview because of the numerous bugs within the program itself and they moved back to HDMI directly to the GIO.

By bugs (and I watched this myself) I'm taking about the cue list resetting to the top randomly in both qlab and eos displays. For eos sometimes the current cue wasn't highlighted. For qlab this show uses groups for everything and cue view doesn't deal with those as well as I think it should. It also stops displaying the time left on cues that are loops.

Note that these bugs I discovered on the raspi but also replicated them on my Mac m3

I think there's a lot of potential here in this project especially for my venue. I brought up some thoughts in discussions.

Mainly without a license in this repository everyone's code is copyrighted to themselves and that can cause issues down the road

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants