GUI Perf issue
-
- KVRist
- 69 posts since 27 Nov, 2012
Hi.
i'm building a VST with 4 big animKnobs (86x86) and 3 little ones (53x53) and displays for all of them.
i set the idle rate to 50 ms.
The result is a CPU load of 100% on idle (25 % of my Quad Core) and it's not smooth when i move knobs.
so the question is is it normal considering the size of my knobs; do i have to use smaller knobs? What is the reason?
Setting the idle rate to a high duration gives me an idle CPU load of (36-48%) for 1 CPU (9-12% of my Quad Core, comparing to 2% without this plugin).
also i should add that the processing is minimal it's a simple compressor with not a lot of calculations so it's the GUI the problem.
thanks for your help.
i'm building a VST with 4 big animKnobs (86x86) and 3 little ones (53x53) and displays for all of them.
i set the idle rate to 50 ms.
The result is a CPU load of 100% on idle (25 % of my Quad Core) and it's not smooth when i move knobs.
so the question is is it normal considering the size of my knobs; do i have to use smaller knobs? What is the reason?
Setting the idle rate to a high duration gives me an idle CPU load of (36-48%) for 1 CPU (9-12% of my Quad Core, comparing to 2% without this plugin).
also i should add that the processing is minimal it's a simple compressor with not a lot of calculations so it's the GUI the problem.
thanks for your help.
-
- KVRist
- 32 posts since 16 Jun, 2006
how do you "move" the knobs? I often use a 128 * 86 * 86 picture as knobs,ion_one wrote:Hi.
i'm building a VST with 4 big animKnobs (86x86) and 3 little ones (53x53) and displays for all of them.
i set the idle rate to 50 ms.
The result is a CPU load of 100% on idle (25 % of my Quad Core) and it's not smooth when i move knobs.
so the question is is it normal considering the size of my knobs; do i have to use smaller knobs? What is the reason?
Setting the idle rate to a high duration gives me an idle CPU load of (36-48%) for 1 CPU (9-12% of my Quad Core, comparing to 2% without this plugin).
also i should add that the processing is minimal it's a simple compressor with not a lot of calculations so it's the GUI the problem.
thanks for your help.
cpu load is normal, even on my old Pentium 4.
-
AdmiralQuality AdmiralQuality https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=83902
- Banned
- 6657 posts since 10 Oct, 2005 from Toronto, Canada
It's not the size of your knobs. (Knobs that aren't moving don't use ANY CPU.) It's obviously something else. Do you have in infinite loop in there or something?
Also you don't tell us any details about your implementation. Is it VSTGUI you're using? What version and rev? On what platform are you observing this? Windows, Windows x64, OSX or OSX x64?
And are you sure your DSP process isn't using any of that CPU power?
Also you don't tell us any details about your implementation. Is it VSTGUI you're using? What version and rev? On what platform are you observing this? Windows, Windows x64, OSX or OSX x64?
And are you sure your DSP process isn't using any of that CPU power?
-
- KVRist
- Topic Starter
- 69 posts since 27 Nov, 2012
hi to you both and thank you for your answers.
i use VSTGUI and it's v3.5.2 and i'm on Windows 7 x64
also i use Visual C++ the last version.
I tried to eliminate the differentes parts of the CPU overload and i found that it's the VU meters that overload the CPU.
The weird thing is that when i leave only one VU meter the CPU peaks at 12% and when i use both, it goes up to 31 % (of the Quad Core). how come ?
alos i found that removing setDirty() from the overrided setValue() of the VU meter class, i got normal CPU load (but no drawing at all)
here is some code :
first the code of the VU Meter then some other codes involving the VU meters:
CDispVU.cpp:
CDispVU.H:
in againeditor.cpp:
also i add this at the end of the process() function inside again.cpp :
also i add this during the process() function
same for the R channel.
Also when i mute all the functions of the VU class, the CPU is still overloaded (there is nothing left in the class except the constructor and destructor and setValue) only when i mute setDirty() in the setValue() function the CPU load drops...
thanks for any help.
Jeff
i use VSTGUI and it's v3.5.2 and i'm on Windows 7 x64
also i use Visual C++ the last version.
I tried to eliminate the differentes parts of the CPU overload and i found that it's the VU meters that overload the CPU.
The weird thing is that when i leave only one VU meter the CPU peaks at 12% and when i use both, it goes up to 31 % (of the Quad Core). how come ?
alos i found that removing setDirty() from the overrided setValue() of the VU meter class, i got normal CPU load (but no drawing at all)
here is some code :
first the code of the VU Meter then some other codes involving the VU meters:
CDispVU.cpp:
Code: Select all
#include "CDispVU.h"
#include "again.h"
#include "againeditor.h"
#include "math.h"
#include <time.h>
#include <stdio.h>
#define VSTGUI3
namespace Steinberg {
namespace Vst {
///////////////////////////////////////////////////////////////////////////////
bool CDispVU::_impair(int nb)
{
return nb&1;
}
bool CDispVU::_impair(long nb)
{
return nb&1;
}
///////////////////////////////////////////////////////////////////////////////
CMouseEventResult CDispVU::onMouseDown (CPoint& where, const long& buttons)
{
beginEdit ();
return onMouseMoved (where, buttons);
}
//------------------------------------------------------------------------
CMouseEventResult CDispVU::onMouseUp (CPoint& where, const long& buttons)
{
peak = false;
cdv->peak = false;
endEdit ();
return kMouseEventHandled;
}
//------------------------------------------------------------------------
CMouseEventResult CDispVU::onMouseMoved (CPoint& where, const long& buttons)
{
bounceValue ();
if (isDirty () && listener)
listener->valueChanged (this);
//if (isDirty ())
invalid ();
return kMouseEventHandled;
}
CDispVU::~CDispVU()
{
}
void CDispVU::setValue(float value)
{
vu = value;
setDirty(true);
}
float CDispVU::getValue()
{
return vu;
}
}}
Code: Select all
#include "againeditor.h"
#include "math.h"
#include "time.h"
#include <base\source\fthread.h>
#include "CDispAffichage.h"
#ifndef __CDISPVU_H
#define __CDISPVU_H
namespace Steinberg {
namespace Vst {
#define VSTGUI3
class CDispVU: public CControl
{
public :
CDispVU(CDispAffichage* cda, CDispVU* cdvi, CRect& size, CPoint pos, CControlListener *listener, int tag, CBitmap *pBackground, CBitmap *bitmap, float step): CControl (size, listener, tag),
bitmap (bitmap), step(step)
{
vu = 0.1;
cdv = cdvi;
cdaInputPeak = cda;
largeur = pBackground->getWidth();
hauteur = pBackground->getHeight();
setBackground (pBackground);
bitmap->remember();
pBackground->remember();
peak = false;
peakTest = true;
};
~CDispVU();
long lastClock;
bool peak;
bool peakShort;
virtual void draw(CDrawContext *pContext)
{
CColor backgroundColor = {225, 204, 26, 0};
CColor redColor = {225, 4, 6, 0};
pBackground->drawTransparent(pContext, size, pos);
//bitmap->draw(pContext, size, pos);
float db;
if (vu > 0.f)
{
db = 20*log10(vu);
}
else db = -90;
//cdaInputPeak->setValue((db + 90)/90.);
if (db < -48) db = -48;
float vuf = ((db + 48)/48.);
if (peak && peakTest/*vuf > 1.f*/)
{
//peak = true;
lastClock = clock();
peakTest = false;
}
int nbSteps = (hauteur-7-21)/step ;
int h = (1.f-vuf) * nbSteps;
if (vuf == 1.f)
{
peakShort = true;
lastClock = clock();
}
if (vuf > 0)
{
CRect cr = CRect(this->getVisibleSize().x, this->getVisibleSize().y+ h*step+21, this->getVisibleSize().x+largeur, this->getVisibleSize().y+ (nbSteps) * step+21);
CPoint cp = CPoint(0, h*step+21);
bitmap->drawTransparent(pContext, cr, cp);
}
if ((peak && (clock() - lastClock) / (double) CLOCKS_PER_SEC < 2.4)
|| (peakShort && (clock() - lastClock) / (double) CLOCKS_PER_SEC < 0.2))
{
CRect cr = CRect(this->getVisibleSize().x, this->getVisibleSize().y , this->getVisibleSize().x+largeur, this->getVisibleSize().y+ 20);
CPoint cp = CPoint(0, 0);
bitmap->drawTransparent(pContext, cr, cp);
}
else
{
peak = false;
peakTest = true;
peakShort = false;
}
setDirty (false);
}
virtual CMouseEventResult onMouseDown (CPoint& where, const long& buttons);
virtual CMouseEventResult onMouseUp (CPoint& where, const long& buttons);
virtual CMouseEventResult onMouseMoved (CPoint& where, const long& buttons);
void setValue(float value);
float getValue();
FThread* ft;
//------------------------------------------------------------------------
CDispVU* cdv;
CDispAffichage* cdaInputPeak;
float vu;
CLASS_METHODS (CDispVU, CControl)
//------------------------------------------------------------------------
protected:
bool _impair(int nb);
bool _impair(long nb);
CRect siz;
CPoint pos;
CBitmap *bitmap;
CBitmap *bckg;
float step;
long largeur, hauteur;
bool peakTest;
};
}}
#endifCode: Select all
CMessageResult AGainEditorView::notify (CBaseObject* sender, const char* message)
{
if (message == CVSTGUITimer::kMsgTimer)
{
if (VU_L_Input_Display)
{
VU_L_Input_Display->setValue (lastVuMeterInputLValue);
}
if (VU_R_Input_Display)
{
VU_R_Input_Display->setValue (lastVuMeterInputRValue);
}
if (VU_L_Output_Display)
{
VU_L_Output_Display->setValue (lastVuMeterOutputLValue);
}
if (VU_R_Output_Display)
{
VU_R_Output_Display->setValue (lastVuMeterOutputRValue);
}
}
return VSTGUIEditor::notify (sender, message);
}Code: Select all
//---3) Write outputs parameter changes-----------
IParameterChanges* paramChanges = data.outputParameterChanges;
// a new value of VuMeter will be sent to the host
// (the host will send it back in sync to our controller for updating our editor)
if (paramChanges && fVuPPMInputLOld != fVuPPMInputL)
{
int32 index = 0;
IParamValueQueue* paramQueue = paramChanges->addParameterData (kVuPPMInputLId, index);
if (paramQueue)
{
int32 index2 = 0;
paramQueue->addPoint (0, fVuPPMInputL, index2);
}
}
if (paramChanges && fVuPPMInputROld != fVuPPMInputR)
{
int32 index = 0;
IParamValueQueue* paramQueue = paramChanges->addParameterData (kVuPPMInputRId, index);
if (paramQueue)
{
int32 index2 = 0;
paramQueue->addPoint (0, fVuPPMInputR, index2);
}
}
fVuPPMInputLOld = fVuPPMInputL;
fVuPPMInputROld = fVuPPMInputR;
if (paramChanges && fVuPPMOutputLOld != fVuPPMOutputL)
{
int32 index = 0;
IParamValueQueue* paramQueue = paramChanges->addParameterData (kVuPPMOutputLId, index);
if (paramQueue)
{
int32 index2 = 0;
paramQueue->addPoint (0, fVuPPMOutputL, index2);
}
}
if (paramChanges && fVuPPMOutputROld != fVuPPMOutputR)
{
int32 index = 0;
IParamValueQueue* paramQueue = paramChanges->addParameterData (kVuPPMOutputRId, index);
if (paramQueue)
{
int32 index2 = 0;
paramQueue->addPoint (0, fVuPPMOutputR, index2);
}
}
fVuPPMOutputLOld = fVuPPMOutputL;
fVuPPMOutputROld = fVuPPMOutputR;Code: Select all
tmp = *ptrIn++;
tmpEnv = tmp;
tmpBass = fc[i]->lowpass(tmp);
tmpEnvBass = tmpBass;
}
float abstmp = fabs(tmp);
if (i == 0)
{
if (abstmp > fVuPPMInputL) {
fVuPPMInputL = abstmp;
}
if (fpeakInputValueL < abstmp)
{
fpeakInputValueL = abstmp;
}
if (abstmp > 1.0)
fpeakInputL = true;
}Also when i mute all the functions of the VU class, the CPU is still overloaded (there is nothing left in the class except the constructor and destructor and setValue) only when i mute setDirty() in the setValue() function the CPU load drops...
thanks for any help.
Jeff
-
AdmiralQuality AdmiralQuality https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=83902
- Banned
- 6657 posts since 10 Oct, 2005 from Toronto, Canada
If you can, try going to VSTGUI 3.6 Latest/greatest is RC2 http://sourceforge.net/projects/vstgui/ ... TGUI%203.6
It already has a CVuMeter class that does what you want. (3.5 might have had it too, I forget offhand.)
I haven't read over every line of your implementation, but you shouldn't be using a timer. Rather, updates to the meter values should be made in the editor's idle() function.
It already has a CVuMeter class that does what you want. (3.5 might have had it too, I forget offhand.)
I haven't read over every line of your implementation, but you shouldn't be using a timer. Rather, updates to the meter values should be made in the editor's idle() function.
-
- KVRist
- Topic Starter
- 69 posts since 27 Nov, 2012
that's nonsense! : i created a totally empty class from CControl and just modified the setValue() function as that :
and i got 100% CPU load! i really don't get it
Code: Select all
void CDispVU::setValue(float value)
{
vu = value;
setDirty(true);
}
-
- KVRist
- 315 posts since 18 Mar, 2012
Perhaps, your timer is so fast that updates too often and keeps the cpu busy.
In any case, the code at the bottom of the "process" method, the one that deals with "outputs parameter changes", should already update the meters. So perhaps, you are updating more often than needed.
In any case, the code at the bottom of the "process" method, the one that deals with "outputs parameter changes", should already update the meters. So perhaps, you are updating more often than needed.
-
- KVRian
- 1087 posts since 12 Jul, 2009 from Brighton
Hi,
First off, don't call invalid() unless you know EXACTLY why you are calling it.
You +don't+ have a reason to call it here. And why bounceValue() when you're not changing it?
Second, when you get called to draw(), you draw()!! You CANNOT throttle inside draw(). It's FAR too late by that point, and the cost of drawing your bitmap is zero compared to other redraw costs that will be going on.
If you want to throttle, do it inside notify(), when you're testing that it's a timer notification.
Fix those and report back.
Dave.
First off, don't call invalid() unless you know EXACTLY why you are calling it.
You +don't+ have a reason to call it here. And why bounceValue() when you're not changing it?
Second, when you get called to draw(), you draw()!! You CANNOT throttle inside draw(). It's FAR too late by that point, and the cost of drawing your bitmap is zero compared to other redraw costs that will be going on.
If you want to throttle, do it inside notify(), when you're testing that it's a timer notification.
Fix those and report back.
Dave.
[ DMGAudio ] | [ DMGAudio Blog ] | dave AT dmgaudio DOT com
-
- KVRist
- Topic Starter
- 69 posts since 27 Nov, 2012
thank you both of you for your precious answers
Out of depiction, i even changed the whole VU class to match the CVUmeter from Steinberg but i still got that heavy CPU load...

okay i restored the initial state i even muted all to see if it improved the CPU load but nothingFirst off, don't call invalid() unless you know EXACTLY why you are calling it.
You +don't+ have a reason to call it here. And why bounceValue() when you're not changing it?
i did what you said but i got no improvement. I even muted all the draw function to see if it was coming from there but no luck...Second, when you get called to draw(), you draw()!! You CANNOT throttle inside draw(). It's FAR too late by that point, and the cost of drawing your bitmap is zero compared to other redraw costs that will be going on.
If you want to throttle, do it inside notify(), when you're testing that it's a timer notification.
that's a good guess but how do i know if the timer is too fast ? i set it on 50 ms rate i think it's the default but if i increase the rate, the CPU drops for sure but the drawing isn't good anymore..Perhaps, your timer is so fast that updates too often and keeps the cpu busy.
In any case, the code at the bottom of the "process" method, the one that deals with "outputs parameter changes", should already update the meters. So perhaps, you are updating more often than needed.
Out of depiction, i even changed the whole VU class to match the CVUmeter from Steinberg but i still got that heavy CPU load...
-
- KVRist
- 315 posts since 18 Mar, 2012
Does the AGain (VST3) example use a timer?ion_one wrote:that's a good guess but how do i know if the timer is too fast ? i set it on 50 ms rate i think it's the default but if i increase the rate, the CPU drops for sure but the drawing isn't good anymore..Perhaps, your timer is so fast that updates too often and keeps the cpu busy.
In any case, the code at the bottom of the "process" method, the one that deals with "outputs parameter changes", should already update the meters. So perhaps, you are updating more often than needed.
Out of depiction, i even changed the whole VU class to match the CVUmeter from Steinberg but i still got that heavy CPU load...
According to what it's written in the comment, the refresh of the vumeter should be scheduled by setting the "outputs parameter changes" stuff, at the bottom of the process method. What happens if you disable the timer?
-
- KVRist
- Topic Starter
- 69 posts since 27 Nov, 2012
here is a full working project for Visual Studio C++ 10 with only the VU meters
i peak at 11% of the CPU (44% of one CPU) so it's still way too much CPU use.
http://khaelis.com/tmp/test.zip
thanks for help
i peak at 11% of the CPU (44% of one CPU) so it's still way too much CPU use.
http://khaelis.com/tmp/test.zip
thanks for help
-
- KVRist
- 315 posts since 18 Mar, 2012
I don't have vs2010.
Anyway, "cvmeter" that you find in "vstgui" doesn't seem to have a "setDirty" in "setValue" (which comes from "ccontrol"). So perhaps, it's just a matter of undestanding how "cvmeter" works.
Anyway, "cvmeter" that you find in "vstgui" doesn't seem to have a "setDirty" in "setValue" (which comes from "ccontrol"). So perhaps, it's just a matter of undestanding how "cvmeter" works.
-
- KVRist
- Topic Starter
- 69 posts since 27 Nov, 2012
what exactly do you call a timer in my code, can't find out...if it's the setIdleRate method in the constructor of AgainEditorView, when i raise the delay, i have no more redraw...bitwise wrote:Does the AGain (VST3) example use a timer?
According to what it's written in the comment, the refresh of the vumeter should be scheduled by setting the "outputs parameter changes" stuff, at the bottom of the process method. What happens if you disable the timer?
for the code itself, i copied the code from AGain without too much change (but still too much apparently)
thanks for your help
-
AdmiralQuality AdmiralQuality https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=83902
- Banned
- 6657 posts since 10 Oct, 2005 from Toronto, Canada
Just FYI I assumed we were talking about VST 2.4. I'm not sure if what I said about timers and idle applies in VST 3.x. (When you said 3.5.2 above I thought you were talking about the VSTGUI version. As far as I know, VSTGUI 4 is what comes with the VST 3.whatever SDK.)
-
- KVRist
- 315 posts since 18 Mar, 2012
This is the timerion_one wrote:what exactly do you call a timer in my code, can't find out...if it's the setIdleRate method in the constructor of AgainEditorView, when i raise the delay, i have no more redraw...bitwise wrote:Does the AGain (VST3) example use a timer?
According to what it's written in the comment, the refresh of the vumeter should be scheduled by setting the "outputs parameter changes" stuff, at the bottom of the process method. What happens if you disable the timer?
for the code itself, i copied the code from AGain without too much change (but still too much apparently)
thanks for your help
Code: Select all
CMessageResult AGainEditorView::notify (CBaseObject* sender, const char* message)
{
if (message == CVSTGUITimer::kMsgTimer)
{
...
As you say, calling "setDirty" in "setValue" slows down the gui and i couldn't find "setDirty" used in such a way in AGain or in the CVMeter contained in VSTGUI. So, I would take a look at cvmeter.cpp. It repaints calling "invalid" in CVuMeter::onIdle.

