If anyone's interested --
I spent a few hours this evening looking at decreasing mixxx's CPU utilization 
while idle -- currently, on my machine, I have two mixxx threads hover at 
around 15% cpu utilization while idle (waveform rendering on, no decks loaded, 
mixxx just initialized) (this is in trunk). With the attached patch, one of 
those threads drops to between 7 and 8% (~50% improvement).

What I've done:
First was to make the engine stop processing nothing. Trunk currently sends 
buffers full of 0.0f's through the eq's, faders, etc. These aren't particularly 
computationally expensive (as I learned in the process of all this), but they 
account for a few % utilization. I solve this by giving enginebuffer a public 
isPlaying method (as enginebuffer has access to the play button), and if both 
buffers aren't playing I simply fill the buffers to the sound device with zeros 
and jump out of the enginemaster::process method. Not filling the buffers with 
zeros leads to nasty things when one pauses a deck, leaving no decks playing; 
i.e. the previous samples are simply played continuously until play is clicked 
again.
After this didn't do me a whole lot of good (1-2% utilization saved), I moved 
on to sounddeviceportaudio::callbackProcess, which is/was a bit of a hog 
according to profiling. Specifically, the QListIterator stuff seems like it 
either likes allocating and copying memory, or maybe just sits and fires 
NOOP... either way, according to the qt docs using qlist::at() is faster and 
no more dangerous (in regards to thread safety) than using an iterator, so I 
modified code to do so.

Anyway, the first bit (disabling enginemaster processing on silence) is worth 
about 2% CPU utilization on idle on my machine, and the second bit is worth 
about 5% CPU utilization (on idle, on my machine) -- both numbers can be +-2%.

Giant disclaimer: I don't deem this patch in any way ready or proper to go to 
trunk, it may burn your house down, set your car on fire, or eat all your 
vinyl. But if anyone else is interested in getting mixxx's cpu usage on idle 
down (ideally to 0!), this might be something to reference in the future.

Thanks to Sean for pointing me in the right direction in regards to profiling.

Bill
=== modified file 'mixxx/src/engine/enginebuffer.cpp'
--- mixxx/src/engine/enginebuffer.cpp	2010-03-20 21:14:06 +0000
+++ mixxx/src/engine/enginebuffer.cpp	2010-05-18 06:17:41 +0000
@@ -257,6 +257,11 @@
     return group;
 }
 
+bool EngineBuffer::isPlaying() const
+{
+    return playButton->get();
+}
+
 double EngineBuffer::getRate()
 {
     return m_pRateControl->getRawRate();

=== modified file 'mixxx/src/engine/enginebuffer.h'
--- mixxx/src/engine/enginebuffer.h	2010-01-29 05:08:12 +0000
+++ mixxx/src/engine/enginebuffer.h	2010-05-18 06:11:09 +0000
@@ -99,6 +99,7 @@
     void process(const CSAMPLE *pIn, const CSAMPLE *pOut, const int iBufferSize);
 
     const char* getGroup();
+    bool isPlaying() const;
 public slots:
     void slotControlPlay(double);
     void slotControlStart(double);

=== modified file 'mixxx/src/engine/enginemaster.cpp'
--- mixxx/src/engine/enginemaster.cpp	2009-10-04 04:17:32 +0000
+++ mixxx/src/engine/enginemaster.cpp	2010-05-18 08:08:30 +0000
@@ -36,6 +36,7 @@
 #endif
 // #include "enginebuffermasterrate.h"
 #include <QDebug>
+#include <cstring> // for memset
 
 EngineMaster::EngineMaster(ConfigObject<ConfigValue> * _config,
                            EngineBuffer * _buffer1, EngineBuffer * _buffer2,
@@ -167,6 +168,12 @@
 void EngineMaster::process(const CSAMPLE *, const CSAMPLE *pOut, const int iBufferSize)
 {
     CSAMPLE **pOutput = (CSAMPLE**)pOut;
+    
+    if (!buffer1->isPlaying() && !buffer2->isPlaying()) {
+        memset(m_pHead, 0, sizeof(CSAMPLE) * iBufferSize);
+        memset(m_pMaster, 0, sizeof(CSAMPLE) * iBufferSize);
+        return;
+    }
 
     //
     // Process the buffer, the channels and the effects:

=== modified file 'mixxx/src/sounddeviceportaudio.cpp'
--- mixxx/src/sounddeviceportaudio.cpp	2010-03-20 20:24:27 +0000
+++ mixxx/src/sounddeviceportaudio.cpp	2010-05-18 07:34:20 +0000
@@ -361,11 +361,13 @@
 			//Interlace Audio data onto portaudio buffer
 			//We iterate through the source list to find out what goes in the buffer
 			//data is interlaced in the order of the list
-			QListIterator<AudioSource> devItr(m_audioSources);
+			//QListIterator<AudioSource> devItr(m_audioSources);
 			int iChannel;
-			while(devItr.hasNext())
+			//while(devItr.hasNext())
+            for (int i = 0; i < m_audioSources.length(); ++i)
 			{
-				AudioSource src = devItr.next();
+				//const AudioSource& src = devItr.next();
+                const AudioSource& src = m_audioSources.at(i);
 				int iLocalFrameBase = (iFrameBase/iFrameSize) * src.channels;
 				for(iChannel = 0; iChannel < src.channels; iChannel++)	//this will make sure a sample from each channel is copied
 				{

------------------------------------------------------------------------------

_______________________________________________
Mixxx-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mixxx-devel

Reply via email to