Albert Santoni wrote:
On Sun, Apr 26, 2009 at 1:33 PM, Andreas Pflug
<[email protected]> wrote:
Using the outline skin on Debian 5.0, I see mixxx consuming 13 % CPU, and
xorg 32% even when there's no visual change.

Digging a little on the performance issues mentioned in the wiki, I found
that preventing ControlObject from changing unchanged values does the trick,
see attached trivial patch against trunk. It reduces xorg CPU usage to a
minimum when there's no display update.

As soon as I play, the cpu usage rises again (mostly in xorg, caused by
wVuMeter updates), which I reduced drastically by using repaint() instead of
update() in WWidget::setValue().

Regards,

Andreas
-devel

Hi Andreas,

Thanks for the patch. I like the ControlObject patch, since one branch
is a lot less costly than all the crazy mutex locking that goes on
after that.

I'm not so sure about the repaint() vs. update() patch though. The Qt
docs are pretty clear about the usage of repaint():

"We suggest only using repaint() if you need an immediate repaint, for
example during animation. In almost all circumstances update() is
better, as it permits Qt to optimize for speed and minimize flicker."
[1]

The VU meter is basically an animation, so maybe this is a good case
to use repaint(). However in that case, I think the update() call
should be placed in a new WVuMeter::setValue() function that overrides
the WWidget one. I'm worried that we're going to cause flickering and
perhaps performance decreases on other operating systems if we use
repaint() for all widgets.

Does this make sense? (If it does, please make the changes and send us
an updated patch, and we'd be happy to commit it. If it doesn't, let's
discuss it...)

This is it.

Regards,
Andreas
Index: src/engine/enginevumeter.cpp
===================================================================
--- src/engine/enginevumeter.cpp	(revision 2748)
+++ src/engine/enginevumeter.cpp	(working copy)
@@ -59,23 +59,31 @@
     m_iSamplesCalculated += iBufferSize/2;
 
     // Are we ready to update the VU meter?:
-    if (m_iSamplesCalculated*2 > (44100/UPDATE_RATE) )
+    if (m_iSamplesCalculated > (44100/2/UPDATE_RATE) )
     {
-        m_fRMSvolumeL = log10(m_fRMSvolumeSumL/(m_iSamplesCalculated*1000)+1);
-        m_fRMSvolumeR = log10(m_fRMSvolumeSumR/(m_iSamplesCalculated*1000)+1);
-        m_ctrlVuMeterL->set( math_min(1.0, math_max(0.0, m_fRMSvolumeL)) );
-        m_ctrlVuMeterR->set( math_min(1.0, math_max(0.0, m_fRMSvolumeR)) );
+        doSmooth(m_fRMSvolumeL, log10(m_fRMSvolumeSumL/(m_iSamplesCalculated*1000)+1));
+	doSmooth(m_fRMSvolumeR, log10(m_fRMSvolumeSumR/(m_iSamplesCalculated*1000)+1));
 
-        FLOAT_TYPE m_fRMSvolume = (m_fRMSvolumeL + m_fRMSvolumeR) / 2;
-        FLOAT_TYPE m_fRMSvolumePrev = m_fRMSvolume;
-        FLOAT_TYPE smoothFactor;
-        // Smooth the output
-        smoothFactor = (m_fRMSvolumePrev > m_fRMSvolume) ? DECAY_SMOOTHING : ATTACK_SMOOTHING;
-        m_fRMSvolume = m_fRMSvolumePrev + smoothFactor * (m_fRMSvolume - m_fRMSvolumePrev);
-        m_ctrlVuMeter->set( math_min(1.0, math_max(0.0, m_fRMSvolume)) );
-        // Reset calculation:
+	m_ctrlVuMeterL->set(m_fRMSvolumeL);
+        m_ctrlVuMeterR->set(m_fRMSvolumeR);
+        m_ctrlVuMeter->set( (m_fRMSvolumeL + m_fRMSvolumeR) / 2);
+
+	    // Reset calculation:
         m_iSamplesCalculated = 0;
         m_fRMSvolumeSumL = 0;
         m_fRMSvolumeSumR = 0;
     }
 }
+
+
+ void EngineVuMeter::doSmooth(FLOAT_TYPE &currentVolume, FLOAT_TYPE newVolume)
+{
+	if (currentVolume > newVolume)
+		currentVolume -= DECAY_SMOOTHING * (currentVolume - newVolume);
+	else
+		currentVolume += ATTACK_SMOOTHING * (newVolume - currentVolume);
+	if (currentVolume < 0)
+		currentVolume=0;
+	if (currentVolume > 1.0)
+		currentVolume=1.0;
+}
Index: src/engine/enginevumeter.h
===================================================================
--- src/engine/enginevumeter.h	(revision 2748)
+++ src/engine/enginevumeter.h	(working copy)
@@ -24,8 +24,8 @@
 
 //SMOOTHING FACTORS
 //Must be from 0-1 the lower the factor, the more smoothing that is applied
-#define ATTACK_SMOOTHING .85
-#define DECAY_SMOOTHING .4//.16//.4
+#define ATTACK_SMOOTHING 1. // .85
+#define DECAY_SMOOTHING .1  //.16//.4
 
 class ControlPotmeter;
 
@@ -43,7 +43,9 @@
     FLOAT_TYPE m_fRMSvolumeSumL;
     FLOAT_TYPE m_fRMSvolumeR;
     FLOAT_TYPE m_fRMSvolumeSumR;
-    FLOAT_TYPE m_iSamplesCalculated;
+    int m_iSamplesCalculated;
+
+    void doSmooth(FLOAT_TYPE &currentVolume, FLOAT_TYPE newVolume);
 };
 
 #endif
Index: src/widget/wvumeter.cpp
===================================================================
--- src/widget/wvumeter.cpp	(revision 2748)
+++ src/widget/wvumeter.cpp	(working copy)
@@ -91,7 +91,7 @@
 
 void WVuMeter::setValue(double fValue)
 {
-    int idx = (int)(m_fValue*(float)(m_iNoPos)/128.);
+    int idx = (int)(fValue * (float)(m_iNoPos)/128.);
     // Range check
     if (idx>m_iNoPos)
         idx = m_iNoPos;
@@ -99,7 +99,8 @@
         idx = 0;
 
     setPeak(idx);
-    WWidget::setValue(fValue);
+    m_fValue = fValue;
+    repaint();
 }
 
 void WVuMeter::setPeak(int pos)
Index: src/controlpotmeter.cpp
===================================================================
--- src/controlpotmeter.cpp	(revision 2748)
+++ src/controlpotmeter.cpp	(working copy)
@@ -87,6 +87,8 @@
 
 void ControlPotmeter::setValueFromThread(double dValue)
 {
+    if (dValue == m_dValue) return;
+
     if (dValue>m_dMaxValue)
         m_dValue = m_dMaxValue;
     else if (dValue<m_dMinValue)
Index: src/controlobject.cpp
===================================================================
--- src/controlobject.cpp	(revision 2748)
+++ src/controlobject.cpp	(working copy)
@@ -165,12 +165,16 @@
 
 void ControlObject::setValueFromThread(double dValue)
 {
+    if (m_dValue == dValue) return;
+
     m_dValue = dValue;
     emit(valueChanged(m_dValue));
 }
 
 void ControlObject::set(double dValue)
 {
+    if (m_dValue == dValue) return;
+
     setValueFromEngine(dValue);
     m_sqQueueMutexChanges.lock();
     m_sqQueueChanges.enqueue(this);
@@ -179,6 +183,8 @@
 
 void ControlObject::add(double dValue)
 {
+    if (!dValue) return;
+
     setValueFromEngine(m_dValue+dValue);
     m_sqQueueMutexChanges.lock();
     m_sqQueueChanges.enqueue(this);
@@ -187,6 +193,8 @@
 
 void ControlObject::sub(double dValue)
 {
+    if (!dValue) return;
+
     setValueFromEngine(m_dValue-dValue);
     m_sqQueueMutexChanges.lock();
     m_sqQueueChanges.enqueue(this);
------------------------------------------------------------------------------
Register Now & Save for Velocity, the Web Performance & Operations 
Conference from O'Reilly Media. Velocity features a full day of 
expert-led, hands-on workshops and two days of sessions from industry 
leaders in dedicated Performance & Operations tracks. Use code vel09scf 
and Save an extra 15% before 5/3. http://p.sf.net/sfu/velocityconf
_______________________________________________
Mixxx-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mixxx-devel

Reply via email to