A quest for better session response times

Hi,

From the first time I came into contact of Open Stage Control I have been thoroughly enjoyed it.
I'm still very grateful to Jean-Emmanuel.

However I started to notice slower response times (lag) when the template grew (to many hundreds of widgets). Lately I came to realize the template as I had imagined will become too slow to be comfortably usable on most devices. The large number of widgets seems to be the main culprit, something other users (and Jean-Emmanuel) also were aware of.

That made me start a quest for more cpu efficiency and quick response times.

So I'm in the process of reducing the number of widgets by making them dynamic. Instead of a dozen of panels with 32 buttons each (only one at a time is visible) I will use a single panel with dynamic properties. These include color, label, messages to be sent, etc. which are set with a script in other button widgets.

All properties are considered performance safe according to the manual.

Details

"Some properties have much cheaper update routines and can be considered as dynamic, as in performance safe. These properties are marked in the documentation with a lightningFastSymbol ." ( Advanced syntaxes - Open Stage Control )

Unfortunately updating the 32 buttons is very slow ! About ten times slower than switching between 'pre-made' panels. Is there a far more efficient way to make the buttons dynamic?

In my template I use a 2-dimensional array (by creating a variable widget called 'buttonArray' and assigning it an array of properties):

Code
// variables: number, visible, color, saturation, luminance, textColor, textSize, left, top, width, height, MSB, LSB, label

if (value > 0) {
  set('buttonArray',[

//  0   1    2    3    4    5     6      7      8     9      10     11   12   13   14   
//  no. vis. clr  sat. lum. textC textS  left   top   width  height type MSB  LSB  label 

  [ 0,  1,   55,  40,  50,  220,  0.7,    0,    0,    6.25,  50,    3    6,   54,  "AUDIO EDITOR"],
  [ 1,  1,   55,  40,  50,  220,  0.7,    6.25, 0,    6.25,  50,    3    6,   54,  "MIDI  EDITOR"],
  [ 2,  1,   55,  40,  50,  220,  0.7,   12.5,  0,    6.25,  50,    3    6,   54,  "DRUM  EDITOR"],
   
  // 32 buttons in total .................................................................

  [31,  1,  160,  40,  50,  220,  0.7,    6.25, 0,    6.25,  50,    3    6,   54,  "STEP BACK BAR"]
])}

These properties are called upon by the button widgets with #{@{buttonArray}[0][x]}%.
For the first button (nr. 0) it shows like this:

Inspector

Here's an idea what the button panel looks like:

How can I seriously improve the efficiency and responsiveness, if possible at all? Any help is appreciated.

Can you upload the session so that I can do some profiling on it ?

Sure. Is this public forum the only place to send the template to you?

Hi,

Thanks for having a look at my template. I extracted the relevant part from it:
static-dynamic-differences.json (2.3 MB)

Here's a picture with some directions:

The problem is I notice significant more lag with dynamic buttons than with static ones. It's particularly noticable on the NUC and tablet I use in the studio, with a lag time of around 1 second (between press and display change).

Yesterday I ran OSC on a faster machine (Core i5 6500T) which made the dynamic panel more responsive. With a lag time of 0.4 second it is just acceptable to me (I do a lot of switching between panels), although I'm a little worried it may increase when I keep adding functionality to the template. That's also why I have kept a fair bunch of buttons as a way to tax the system, since I know I will need to add several hundreds of widgets anyway for added functionality.

There's one thing I noticed about the dynamic buttons and responsiveness: having the panel control switches and buttons in the same container (a panel) gave really huge lag times. Putting the controls and buttons in two different containers was much better.

As you may see the switching between the static button panels is fast, almost instantly. Switching between the three dynamic panels is noticably slower even though there are only 32 buttons, not a screen full of them. Higher numbers of dynamic buttons and variables lead to slower switching.
It seems it's mostly the reading from the array wich slows it down, less so the writing to the array.

Although a fast computer (plus limiting the number of buttons and variables) will probably be sufficient to deal with the lag, I would of course prefer a solution in the way of more effective coding by the user.

Questions:
Is it completely normal for the dynamic panels in my template to be a bit slow to update?
If so, is there a way to make them update faster while retaining their dynamic character?

I love the idea of using dynamic widgets! This way adding panels doesn't extra tax the system. I also imagine one modal which can pop up anywhere with different buttons and functionality as if it were many of them. And a single vst plugin control panel to use with several different vst plugins.

Thanks, I narrowed the issue to two specific problems that cause VAR{} and @{} to be slow when used intensively with large objects: currently these syntaxes make a copy of their value before returning it to avoid unwanted mutation in #{} or JS{} scripts (see this post for technicals). I will adjust this in next version so that only the scripting functions getVar() and get() behave this way.

Now the best solution regarding performances would be to handle all the magic in a custom module and use the /EDIT command to modify your widgets or even on the fly. This way you can keep the session tight with as few widgets as possible and have most of your javascript in the same place which is much easier to maintain.

Thank you. Do you have a rough estimation of how much faster it will become when the update is ready? It may be worth the wait and make current lag times acceptable with the prospect of future improvements.

In the meanwhile I may try and get acquainted with custom modules, which wil probably take quite a while (and require some help now and then).

Is using /EDIT really faster than using OSC listeners? Using /EDIT seems not very fast either:

  • "Warning - Editing widgets is cpu expensive; for small and recurrent changes, consider using osc listeners instead." (source: manual)
  • "Using /EDIT is way too slow and slows everything up dramatically while it works through." (source)

I have to update about 500 parameters each time when switching banks. Is that considered a large amount and is that why /EDIT is prefered over OSC listeners? And more important: will either of them nevertheless speed up my template considerably despite the cpu-expensiveness? (and so is that alone already worth the time investment learning custom modules? :slight_smile: )

v1.16.0 is uploading (with the aforementioned fix included), this might do for you use case. With such a high number of widgets to update I'm not sure a custom module would do better. Do you have 500 controls at a time on screen ?

Wow, that's quick! (in more than one sense)

I just did some testing and I can say I'm very happy! The new update reduces the lag time considerably. Switching between panels is about 4 times as fast as in previous osc versions. That's exactly what I was hoping for and it more or less solves the problems I had with lag.
So thank you very much! You made my day :slight_smile:

To answer your question: My template will never have more than about 200 controls at the same time on the screen.

Before the v1.16 update, the very frequent switching between panels with only 32 controls (buttons) already gave too much of a lag on slower machines. However fast switching/updating of 200 controls at the same time is not something I will need, as long as smaller groups of dynamic controls will switch quickly.

What I meant with 500 parameters is the number of compound variables withing the buttons, like colorText or width. Because each of those buttons has quite a few VAR{} and @{} variables, it adds up:

Variables withing one dynamic button
visble: #{@{buttonArray}[VAR{buttonNumber}][1]}

left:   #{@{buttonArray}[VAR{buttonNumber}][8]}% 
right:  #{@{buttonArray}[VAR{buttonNumber}][9]}% 
width:  #{@{buttonArray}[VAR{buttonNumber}][10]}% 
height: #{@{buttonArray}[VAR{buttonNumber}][11]}%

colorText: hsla(#{@{buttonArray}[VAR{buttonNumber}][5]},100%,#{@{buttonArray}[VAR{buttonNumber}][6]}%,1)
colorWidget: hsla(#{@{buttonArray}[VAR{buttonNumber}][2]},#{@{buttonArray}[VAR{buttonNumber}][3] + 50*@{this}}%,#{@{buttonArray}[VAR{buttonNumber}][4] + 10*@{this}}%,1)
colorStroke: hsla(#{@{buttonArray}[VAR{buttonNumber}][2]},@{edgeSat}%,@{edgeLum}%,1)

CSS: label {
    font-size: #{@{buttonArray}[VAR{buttonNumber}][7]}vw;
}

:host {
 #{
    @{this} == 1 ? "class: buttonStylePressed;" : "class: buttonStyle";
    }
}

label: #{@{buttonArray}[VAR{buttonNumber}][15]}

Of course I welcome any tips or changes for further improvements in lag times, but today has been a good day for me.

1 Like