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

Sliders move very slow in VST (VST3 in REAPER also) on Linux (all tested hosts) #1103

Closed
mortfell opened this issue Sep 4, 2019 · 96 comments
Labels
Linux Issues which only occur on Linux
Milestone

Comments

@mortfell
Copy link

mortfell commented Sep 4, 2019

Describe the bug
For me the graphics on Surge are really laggy/slow when dragging sliders.
Especially the morph slider in wavetable mode (which changes the wave form display).
I'm using an older computer, but compared to other stuff happening in this install, Surge feels really really sluggish.
VST2 and VST3 are both effected in REAPER

The sliders get even slower if you resize the interface to be larger.
On the LV2 plugin in Ardour and Carla, the Speed of the sliders is totally fine and snappy EXCEPT the morph slider.

SYSTEM INFO
The latest nightly of Surge, first version of Surge to include LV2
I'm on the latest lubuntu 19.04 a lightweight Ubuntu distro.
UNAME printout:
5.0.0-13-generic #14-Ubuntu SMP Mon Apr 15 14:59:14 UTC 2019 x86_64 GNU/Linux
Latest stable Ardour, REAPER, RENOISE and Carla

If if can provide any more specific info am happy to do so!

@mortfell mortfell changed the title Sliders move very slow in VST on Linux (all tested hosts) Sliders move very slow in VST (VST3 in REAPER also) on Linux (all tested hosts) Sep 4, 2019
@baconpaul baconpaul added the Linux Issues which only occur on Linux label Sep 4, 2019
@baconpaul
Copy link
Collaborator

The COscillatorDisplay and CLFODisplay has a downsample for the big vector graphic which are those displays. If Cairo through vstgui is lagging that would probably be the first place to look

@mortfell
Copy link
Author

mortfell commented Sep 4, 2019

Is the slow sliders in VST something only I am experiencing?

@baconpaul
Copy link
Collaborator

I do my basic testing in carla and bitwig and reaper in an ubuntu 18.04 stock VM. VST3 in Reaper in my ubuntu seems fine.

It does seem, though, like the classic mouse mode is a bit more "draggy" on linux than on windows and mac. When I set it to "exact" (in the menu under mouse or some such) though everything feels super responsive. I wonder if there is some scaling factor on linux which is de-amplifying the drag?

@mortfell
Copy link
Author

mortfell commented Sep 5, 2019

For me on VST3 REAPER they all seem a little laggy.
And i mean this computer is oooold it's an AMD CPU from like 2008 or something, but still
the LV2 Surge is very snappy on this same system. Wonder what I could be.

@jpcima
Copy link
Contributor

jpcima commented Sep 5, 2019

If redrawing is responsible for the slowness, then can we mitigate it by redrawing after a well-adjusted short delay?
It should be a single tick retriggerable timer which schedules a redrawing to the event loop.
I think, by a strategy like this, you don't pile up redraw calls to be made in very short time frames.
I haven't examine code as of yet, just suggesting an idea.

@baconpaul
Copy link
Collaborator

Yeah we could; but can we profile it to make sure that's the problem first? It's a bit of a pain to do only-every-other-redraw (but not that bad; basically at the top of COscillatorDisplay and CLFOGUI ::draw you put a counter and skip every n of m redraws; but when you skip you have to mark yourself invalid so you get a chance at the next refresh. If this ends up being needed I could add it easily in an #if LINUX block).

@jpcima
Copy link
Contributor

jpcima commented Sep 5, 2019

Alright, as backup solution then. So that I get my linux profiling, I think it will go about something like this:

  • manage an optimized build like release, but containing debug symbols
  • run it in a minimal host with libprofiler from gperftools (jalv, carla-single), by using the environment LD_PRELOAD
  • move around one of CLFOGui's sliders for some seconds, and save it

@baconpaul
Copy link
Collaborator

From my experience on mac, a full profiler was basically impossible; I had to use "instruments" (which is their time sampling profiler) to get the thing running and profiled. And I had to profile the release version to get anything useful.

I'm not sure what the linux sampling profiler is. Has dtrace made it to your kernel yet? I am 99% sure that's what the mac stack is built on.

@jpcima
Copy link
Contributor

jpcima commented Sep 5, 2019

I'm pretty sure the Linux profiler (well gperftools if it can be called that, I don't know of others)
is based on user space sampling from reconstructing the call trace.
I think the dtrace-like of Linux is SystemTap, I've not used it, nor do I know of potential profiling abilities regarding it.

@baconpaul
Copy link
Collaborator

Ok! My expertise on Linux profiling is a decade or so out of date. Just sharing what worked on Mac!

@jpcima
Copy link
Contributor

jpcima commented Sep 5, 2019

It's what I have obtained from the profiling currently.
Nothing of too great use, because I don't have a complete call stack record of it.
I've never had too much luck about extracting significant info off this software. I will retry with debug system libs and check more docs on it.
profile.pdf.gz

@baconpaul
Copy link
Collaborator

A super easy test to eliminate the problem
if COscillatorDisplay::draw and CLFOGui::draw both just return immediately does the problem go away?

@jpcima
Copy link
Contributor

jpcima commented Sep 5, 2019

A super easy test to eliminate the problem

That yeah, it does, I did this try in CLFOGui before that I suggested a timer, problem was gone then.

This is the version of the profile just remade, more detailed, after setting up debug cairo.
profile.pdf.gz

@baconpaul
Copy link
Collaborator

OK. We can easily downsample more aggressively in the LFO display. There's already downsample code there.

If here

int averagingWindow = 1;
you do a #if LINUX averagingwindow *= 4 then it should get immediately faster.

@jpcima
Copy link
Contributor

jpcima commented Sep 5, 2019

Confirmed !! At 4 it remains laggy a bit but way better, doubling again then it gets almost flawless.

@baconpaul
Copy link
Collaborator

OK cool. So basically "linux through vstgui doesn't have the same vector capacity as mac and windows do". Why don't we, for now, put in a #if linux *8 and open a separate issue to do less frequent draws when dragging that we can get to after 1.6.2 ships.

@jpcima
Copy link
Contributor

jpcima commented Sep 5, 2019

Is the multipler supposed to go after the following loop? on second look, I assume this would be the case, right? (as I did without thinking, I wrote the statement before)

      while( drawnTime / averagingWindow > 3.0 ) // subsample at longer times
          averagingWindow ++;

At 100% zoom, 4x will be actually perfect there.
At 175% zoom, my screen maximum, any value I put in there, it remains slow. It can be up to 128x where the sine is made to look bad like a triangle-ish, it will draw slow regardless under the scaling.

@baconpaul
Copy link
Collaborator

Oh that's really interesting.

It must be something else in the vector drawing API. With averaging window of 128 it's just a small set of lines! And the fact that it worsens with zoom makes me think vstgui may be doing something quite inefficient internally.

Lets leave this alone for now; maybe there's a better way like doing an offscreen draw. I'll try and take a look next week.

@baconpaul
Copy link
Collaborator

Or if you want to look: You can see where I construct the vector and do the draw. We can do things like "don't draw the final path at all" and see if that does it (data structure vs render); or draw to an offscreen context; or as you said draw less frequently.

@baconpaul
Copy link
Collaborator

wow that performance at high zoom is indeed terrible

the zoom doesn't change the number of vector points. Something must be super wrong inside vstgui. I'll see what I can see.

@jpcima
Copy link
Contributor

jpcima commented Sep 5, 2019

Not sure I can be of excellent help here regarding the graphics.
I understand what you mean by the structure/render dichotomy so yeah, probably I'll be able to tell if the problem is isolated to the rendering part.

@baconpaul
Copy link
Collaborator

I just did some profiling by hand.

Of the 12ms spent doing a draw in my VM, 11.5 were spent in the drawGraphicsPath routine for the LFO curve.

More concerningly, this time seems to increase with zoom linearly even though the number of points and so on don't.

So I'll have to dig inside vstgui. I think this one will be one I have to find.

@jpcima
Copy link
Contributor

jpcima commented Sep 5, 2019

Well yes, I've had this function under my eyes exactly as you mention it.
It's because of noting a particular thing: when I disable #if LINUX special cases of the CLFOGui files, which exist for reasons I don't entirely understand, it then draws at zoom 100% a super blocky sine, but then it's fast. (at the higher zooms, it draws nothing)
I've suspected because it sets a different transform matrix for the path, possibly it's the beginning of a track to find the slowness origin.

In all cases, I get too tired to look at this, so I will sleep 😃

@baconpaul
Copy link
Collaborator

Yes that's exactly right

Basically vstgui -> cairo draws in integer space for some reason. So I zoom out 100x then shrink back 100x.

And that seems to be the problem.

All the time is spent in cairo_stroke in vstgui/lib/platform/linux/cairocontext.h

so I need some cairo expertise. What's making the path integral (which is why I do the 100x hack and transform back). That's what I really need to figure out!

@baconpaul
Copy link
Collaborator

More notes to self

vstgui pixel aligns all paths basically way too early with the call to pixelAlign in the cairopath.cpp inside kLine. If you make pixelAlign just return self then you can at least remove the #ifdef LINUXes

So this is clearly something about vstgui linux cairo implementation not doing the same thing as windows and mac with paths.

@baconpaul
Copy link
Collaborator

Sigh ok so these would be bigger changes for a release

This weekend I’m going to do one of two things

1: draw every 4 frames on linux or
2: restore the old bitmap code on Linux

@jpcima I’m happy to do this but don’t want to dampen your contribution. So if you want I bet you can’t figure out #1 just as easily as I could.

but #2 would be way easier for me than you.

My theory currently is vstgui mis integralizes so I make too large a virtual drawing area and that explodes resources quadraticalky in Cairo somewhere. But I can’t find a safe fix hence the above approach

@jpcima
Copy link
Contributor

jpcima commented Sep 6, 2019

About cairo, and pixel alignment: the pixels are not by default aligned on integer coordinates.
It needs to apply a +(0.5,0.5) offset to land on exact pixels, that's the official recommended way.
So, if it's desired that integer must be on pixels, one could simply apply a global translation +(0.5,0.5) at the beginning of drawing. It's my guess.

Now, I believe I found another item of better interest.
In CLFOGui, when you substitute the draw mode setting with: dc->setDrawMode(VSTGUI::kAntiAliasing|VSTGUI::kNonIntegralMode);

Then, I'm able to obtain normal drawing without the linux hack. But then also, it gets slow back again. So, presence of linux hack or not, this wouldn't seem to be the actual problem.

@baconpaul
Copy link
Collaborator

I'm going to reopen this too even though it is a lot better so we at least to remember to either not give up on what you see or find out what it is and give up consciously :)

@baconpaul baconpaul reopened this May 23, 2020
@tank-trax
Copy link
Collaborator

what LFO switch are you talking about?

@xard-dev
Copy link

xard-dev commented May 23, 2020

Yeah, I use 43" 4k monitor so Surge at 300% fits entirely on screen.

@baconpaul
Copy link
Collaborator

OK. Well I will give you a patch for some profiling sometime in the next few days to try out OK?

All VSTGUI optimization ... so lets find out what the next slow bit is.

@xard-dev
Copy link

xard-dev commented May 23, 2020

If you give me "coordinates" or patches for debug prints and I'll gladly test them and report results 😃

@baconpaul
Copy link
Collaborator

OK I have a patch and a theory. The patch doesn't improve anything but I want to know what you see

xard.patch.txt

Save that as vstgui.surge/xard.patch.txt
cd vstgui.surge
git apply xard.patch.txt
rebuild and run with terminal attached

now it will tell you how many rectangles redraw and how long it takes

The interesting thing I see when I mouse down and don't mouse up on an LFO button is

  1. I see a log message with around 80 rectangles that says full is false and time is long
  2. Then immediately I see a log message with 352 rectangles that says full is true and time is short
drawHandler: Sizes dirtyRects=1 newDR=1 isFull=0 time=658 us
drawHandler: Sizes dirtyRects=2 newDR=2 isFull=0 time=1072 us
<< THIS IS WHERE I PRESS MOUSE DOWN BUT NOT MOUSE UP AND SEE THESE IMMEDIATELY
drawHandler: Sizes dirtyRects=89 newDR=89 isFull=0 time=40696 us
drawHandler: Sizes dirtyRects=352 newDR=1 isFull=1 time=5736 us
<<< WAIT
<< PRESS MOUSE UP
drawHandler: Sizes dirtyRects=1 newDR=1 isFull=0 time=597 us
drawHandler: Sizes dirtyRects=2 newDR=2 isFull=0 time=970 us

What do you see in the log with that patch applied?

My bet is that 40696us at 300% is a much much bigger number

I want to know what those non-unique rects are of course. I had a hack for a while that said "if rect count > 30 just repaint everything". Depending on what you see I may give you another patch with that (or if you want, where that patch is applied just change the condition

if( fullWindow )

to

if( fullWindow || newDR.size() > 25 )

a few lines above and see if that helps)

Thanks!

@xard-dev
Copy link

xard-dev commented May 23, 2020

All these benchmarks will be at 300%.

Pushing down mouse button and on each button press LFO item gets changed eventually without letting the mouse button up. Selected

LFO items for "Acid Seq3" from top to bottom:

drawHandler: Sizes dirtyRects=90 newDR=90 isFull=0 time=964269 us
drawHandler: Sizes dirtyRects=90 newDR=90 isFull=0 time=956222 us
drawHandler: Sizes dirtyRects=90 newDR=90 isFull=0 time=908684 us
drawHandler: Sizes dirtyRects=90 newDR=90 isFull=0 time=905244 us
drawHandler: Sizes dirtyRects=90 newDR=90 isFull=0 time=1040504 us
drawHandler: Sizes dirtyRects=90 newDR=90 isFull=0 time=883975 us
drawHandler: Sizes dirtyRects=90 newDR=90 isFull=0 time=918669 us
drawHandler: Sizes dirtyRects=90 newDR=90 isFull=0 time=917785 us

@baconpaul
Copy link
Collaborator

Wow you never get an isfull=1?

@baconpaul
Copy link
Collaborator

And yeah that’s a second of stupid overdraws - why not try and force isfull as I mentioned above. Wonder what those rectangles are - that’s where I will look next

@xard-dev
Copy link

xard-dev commented May 23, 2020

After patching following statement:


if( isFullRefresh || newDR.size() > 25 )
      {
         // We only want to do one repaint
 	 newDR.clear();
	 newDR.push_back( fullWindow );
      }
drawHandler: Sizes dirtyRects=90 newDR=1 isFull=0 time=30363 us
drawHandler: Sizes dirtyRects=90 newDR=1 isFull=0 time=51449 us
drawHandler: Sizes dirtyRects=90 newDR=1 isFull=0 time=47727 us
drawHandler: Sizes dirtyRects=90 newDR=1 isFull=0 time=46440 us
drawHandler: Sizes dirtyRects=90 newDR=1 isFull=0 time=48707 us
drawHandler: Sizes dirtyRects=90 newDR=1 isFull=0 time=47605 us
drawHandler: Sizes dirtyRects=90 newDR=1 isFull=0 time=45163 us
drawHandler: Sizes dirtyRects=90 newDR=1 isFull=0 time=45139 us
drawHandler: Sizes dirtyRects=90 newDR=1 isFull=0 time=74872 us

It's fast, it's almost instant compared to before. 😮

@xard-dev
Copy link

Also changing patches now is almost instant. Nice side effect indeed!

@tank-trax
Copy link
Collaborator

wow these tweaks. thanks guys for your diligence, for providing these reports, and for testing

@baconpaul
Copy link
Collaborator

Right so good now we know the solution - I resisted that deep a hack so lemme see what’s in those 89 rectangles but if I can’t or if I get bored I will apply that count diff to master

(There is a good algorithm for clustering these draws but it is a pain to code so I may just use a hammer with the threshold)

@baconpaul
Copy link
Collaborator

Ahh I see. So basically when you mouse down we refresh each of the sliders - that is insanely inefficient in VSTGUI Linux (and only in VSTGUI Linux).

Can you try one more thing for me and let me know, and then I'll put together a patch

  1. reset to master, including vstgui.surge
git fetch origin
git reset origin/master --hard
cd vstgui.surge
git reset origin/surge --hard

or whatever you prefer

  1. in the surge directory save this and apply it

trythis.patch.txt

  1. build and report back if it is also fixed

if so I will do both that change and the precautionary check at 30 rects in the loop also.

Thanks

@xard-dev
Copy link

This wasn't supposed to be part of the test I presume:
/home/share/sources/surge/surge-git/src/common/unitconversion.h:55:18: error: ‘%i’ directive writing between 1 and 11 bytes into a region of size 8 [-Werror=format-overflow=]

@baconpaul
Copy link
Collaborator

ahh I don't know why those errors pass CI. Hold on.

@xard-dev
Copy link

xard-dev commented May 23, 2020

It's almost if the CI system does not have the format-overflow warning enabled and/or does not fail to them.

@baconpaul
Copy link
Collaborator

Nah I think it is that CI is running on ubuntu 18 and the compiler isn't as smart

@baconpaul
Copy link
Collaborator

Sorry - ubuntu 16! (I should upgrade that!)

@tank-trax
Copy link
Collaborator

it's building here on Debian 10

@baconpaul
Copy link
Collaborator

Yeah I think ubuntu 20 has the compiler upgrade that supports that error.

Anyway: this is the right change. Let me push it to master along with the fix OK? Doing so now.

baconpaul added a commit to baconpaul/surge that referenced this issue May 23, 2020
1. Pipeline to 18.04
2. Fix the sprintf errors
3. Upgrade vstgui in high-rect mode to be faster, closing surge-synthesizer#1103 again
baconpaul added a commit that referenced this issue May 23, 2020
1. Pipeline to 18.04
2. Fix the sprintf errors
3. Upgrade vstgui in high-rect mode to be faster, closing #1103 again
@baconpaul
Copy link
Collaborator

OK just pushed to master. Can you try master no patches now 24f7676
And if that works close this issue?
Thanks!

@xard-dev
Copy link

xard-dev commented May 23, 2020

Note to self: it seems to take around 10 minutes or more for the patches to be available...

Master build 24f7676 with no patches: back to slow update.
Whoops; forgot to pull submodules: testing again.

@xard-dev
Copy link

xard-dev commented May 23, 2020

And after I fixed my mistake the build WITH submodules updated commit 24f7676 is fast again. 👍
(step sequencer seems to have now tooltips for the set values as well)

@baconpaul
Copy link
Collaborator

Yeah wonderful - so I’ll close this

And yes we are doing lots of work on the step sequencer gui right now!! Those tool tips are 3 hours old :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Linux Issues which only occur on Linux
Projects
None yet
Development

No branches or pull requests

7 participants