CPU at 300% without doing anything

Hi,

working on a project I notice that my cpu was crazy, not understanding what it was due to, I decided to start from scratch and I created a simple project that only play the edit and turn click on: the result is that my cpu goes from 250% to 300%… here the MainComponent.h and the MainComponent.cpp and a photo:

MainComponent.h

class MainComponent  : public juce::Component
{
public:
    //==============================================================================
    MainComponent();
    ~MainComponent() override;

    //==============================================================================
    void paint (juce::Graphics&) override;
    void resized() override;

private:
    //==============================================================================
    // Your private member variables go here...
    tracktion_engine::Engine engine{ProjectInfo::projectName};
    std::unique_ptr<tracktion_engine::Edit> edit;
    TextButton play{"play"};

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainComponent)
};

MainComponent.cpp

MainComponent::MainComponent()
{
    setSize (600, 400);
    edit.reset(new tracktion_engine::Edit{engine, tracktion_engine::createEmptyEdit(engine), tracktion_engine::Edit::forEditing, nullptr, 0});
    addAndMakeVisible(play);
    play.onClick = [this]() {
        if (edit->getTransport().isPlaying())
        {
            edit->getTransport().stop(false, false);
            play.setButtonText("play");
        } else {
            edit->getTransport().play(false);
            play.setButtonText("stop");
        }
    };
// without clickTrackEnabled and clickTrackEmphasiseBars app goes from 100% to 120% of cpu usage
    edit->clickTrackEnabled = true;
    edit->clickTrackEmphasiseBars = true;
}

MainComponent::~MainComponent()
{
}

//==============================================================================
void MainComponent::paint (juce::Graphics& g)
{
}

void MainComponent::resized()
{
    play.setBounds(getLocalBounds());
}

perhaps use a breakpoint to determine if the lambda is recursive.

i.e. by calling methods on the button from inside the lambda, you might be inadvertently triggering the ‘onClick’ callback recursively back into the lambda in a tight loop.

1 Like

Thank you for your reply, but I tried it and It doesn’t seem the problem, using a breakpoint the execution breaks only one time inside lambda

CPU metering isn’t really useful, there’s lots of reasons it could be high.
You really need to profile to see if the reading is actually a problem or not.

One thing you could do is limit the number of CPU cores to 1 for your project (by overriding EngineBehaviour::getNumberOfCPUsToUseForAudio() to return 1). That will stop any spinning or waiting of additional threads and process your audio graph on the audio thread synchronously.

1 Like

I would argue it is always a problem since it can become a thermal and/or a battery draining issue on the hardware. (I also realize it might not be an easy thing to solve.)

1 Like

ok limiting it to 1 core both xCode and activity monitor show me an usage of ~6%, but what does it means, it could be a bug related with the hardware (but I don’t think so because waveform that is
infinitely more complex as app gives me ~60% of cpu usage)? the app as you can see is vey basic, just instantiated an edit…

Compiling in release mode it decreases the cpu usage a lot, but it sounds strange anyway

the problem is rising in an iMac Pro 2017:
cpu: 2,3 GHz Intel Xeon W 18 core
ram: 128 GB 2666 MHz DDR4
graphic card: Radeon Pro Vega 64 16 GB
ssd: 4tb

So if it’s saying 6% that’s fine right?

It’s a bit long and complex to explain but essentially when multi-threading you have to trade off CPU usage and thread wake-up latency. There’s some code in the engine which tries to keep recently used threads spinning for a bit on the assumption they’ll be required soon which stops them going to sleep.

However, if you have a small or simple audio graph it’s probably just bouncing around threads keeping them spinning for now reason and hence using a lot of CPU.

1 Like

I hope so, really thank you, because my app is quite complex and I cannot limit the usage to 1 core (it must give the possibility to use many tracks )… but how to debug be sure?

How do you know you can’t limit it to 1 core? It’s sometimes more efficient to do this.

But I don’t really understand the problem. You’re saying with unlimited cores (i.e. the number of virtual cores you have in your machine), CPU use is 300%. Limited to a single core it is 6%. But neither is a good figure?

I think you need to build your app, use it in a typical way and profile to see where the CPU is being used.

1 Like

I imagine this occurs after clicking play? That would mean that it has to do with the traction_engine, which has almost no documentation at this time. I don’t imagine what else it could be.

Try pausing the execution while the CPU is high, and check the callstack to see if there’s a repeated series of calls listed, to find what JeffMcClintock was suggesting might be a hidden recursive function.

You need to run a profiler to see where the CPU time is being spent.

1 Like

Despite years on the juce forum, it never ceases to amaze me how we get these big threads about CPU problems, where people spend ages explaining in detail what they’re doing, and others write long replies guessing what might possibly be happening, but where nobody has even bothered to do the absolutely basic step of profiling the damn thing!

Literally the first thing anyone should do when they suspect a CPU problem - before asking for help, or experimenting with code changes, or spending any time wondering what might be the cause - is just profile it!!

If this was difficult, it’d be understandable that people don’t do it, but it’s really easy! It saves you a lot of time, and gives you a better understanding of what’s going on in your code.

There’s absolutely no use expecting other people to guess what might be slowing down your app on your machine. If the problem does turn out to be something that should be improved in JUCE or tracktion, you won’t be able to provide a decent bug report without measuring what’s actually happening. And if it’s a problem in your code, then you need to profile it yourself to find it!

(I’ve probably done versions of this rant many times before, but it bears repeating!)

7 Likes

Maybe the message wasn’t clear :wink:

1000% yes.

And there is also a quick and dirty method of ‘profiling’ (I use that term loosely):

Run your code in a debugger. hit ‘break’ then ‘run’ 10 times, noting what code the debugger paused on. If you have a bottleneck it will often reveal itself pretty quickly with this technique. (because you will end of pausing in the same or similar call stack more often than not).

This is what a ‘sampling’ profiler does, except 1000 times per second.

1 Like

Seems like you’ll get more benefits in keeping your app single core, surfing on multithreading is going to make you feeling seasick…

Don’t spend time profiling nor optimising if you run just a few %of a single core, it’s mostly enough for everyone!

Yes, I’d say for most use cases just running a single threaded audio engine is probably fine. It’s really only when you have big audio graphs with lots of tracks on a desktop machine with lots of cores multi-threading gives you huge advantages. It’s also much easier to profile single-core usage.
I might actually make that the default.