Getting CPU statistics
-
- Posts: 624
- Joined: Mon May 12, 2008 10:55 am
Getting CPU statistics
I've been asked to determine CPU usage/loading at runtime? I think this is typically done by comparing how much time the CPU spends in an idle task to the total operating time. But there doesn't seem to be an idle task. If that's true, I can make my own idle task at the lowest priority and sit in a loop calling GetCurrentTaskTime() and calculating the percent usage. If there was a way for one task to read the taskTicks of another task, then my idle task could just spin on an infinite loop doing nothing. Does that seem reasonable?
Also, is there a way to determine how much ram memory is being used during runtime?
We have a very paranoid customer.
I'm using v3.3.7, with a NANO.
Also, is there a way to determine how much ram memory is being used during runtime?
We have a very paranoid customer.
I'm using v3.3.7, with a NANO.
Re: Getting CPU statistics
Running 2.X or 3.X? What Module type?
Free memory:
Under 3.X
Add in user main:
EnableSystemDiagnostics();
Then under the config page you will dind a diag tab.... free memory is one of the entries...
Under 2.X then call
bsp.h:DWORD spaceleft();
CPU the idle task is at :
3.x:
nburn\arch\coldfire\source\nbrtosmain.cpp
nburn\arch\cortex-m7\source\nbrtosmain.cpp
Its in there, just add a volatile counter
Run an app that does nothign but block ain user main and report the counter increment per second... do the same in your app and the ration is cpu usage...
In 2.x Same task is nburn\system\ucos.cpp
If you go into predef than you can turn on an enable some task time monitoring, but its invasive and would not recomend doing this in release...
3.X
#define NBRTOS_TIME (1) *
2.X #define UCOS_TIME (1)
Then to report results:
3.x Call: void ShowTaskTimes(void);
2.x Call void ShowTaskTimes( void );
That should give you what you want...
Free memory:
Under 3.X
Add in user main:
EnableSystemDiagnostics();
Then under the config page you will dind a diag tab.... free memory is one of the entries...
Under 2.X then call
bsp.h:DWORD spaceleft();
CPU the idle task is at :
3.x:
nburn\arch\coldfire\source\nbrtosmain.cpp
nburn\arch\cortex-m7\source\nbrtosmain.cpp
Its in there, just add a volatile counter
Run an app that does nothign but block ain user main and report the counter increment per second... do the same in your app and the ration is cpu usage...
In 2.x Same task is nburn\system\ucos.cpp
If you go into predef than you can turn on an enable some task time monitoring, but its invasive and would not recomend doing this in release...
3.X
#define NBRTOS_TIME (1) *
2.X #define UCOS_TIME (1)
Then to report results:
3.x Call: void ShowTaskTimes(void);
2.x Call void ShowTaskTimes( void );
That should give you what you want...
-
- Posts: 624
- Joined: Mon May 12, 2008 10:55 am
Re: Getting CPU statistics
I'm using v3.3.7 with a NANO.
Our customer wants to be able to query our device for CPU usage and percent of ram used. So it needs to be in the released build.
I'm not sure how a counter would be incremented at a one second rate only when the idle task was running. Plus I don't think the idle task will run for a second at a time. What's the resolution of the value returned by BspGetTickFraction?
Our customer wants to be able to query our device for CPU usage and percent of ram used. So it needs to be in the released build.
I'm not sure how a counter would be incremented at a one second rate only when the idle task was running. Plus I don't think the idle task will run for a second at a time. What's the resolution of the value returned by BspGetTickFraction?
Re: Getting CPU statistics
Where does one second in your comment come from?
The idle task runs whenever nothing else is running, it runs all the time in a big nop loop.
so
Change the idle code from:
static void OSTaskIdle(void *data)
{
data = data;
while (1)
{
asm(" NOP");
asm(" NOP");
asm(" NOP");
asm(" NOP");
asm(" NOP");
asm(" NOP");
asm(" NOP");
asm(" NOP");
asm(" NOP");
// OS_IDLE_LOOP()
}
}
to this:
volatile uint32_t LastLoopCount;
volatile uint32_t LastSecSampled;
static void OSTaskIdle(void *data)
{
data = data;
uint32_t LastSec;
uint32_t Count;
while (1)
{
asm(" NOP");
asm(" NOP");
asm(" NOP");
asm(" NOP");
asm(" NOP");
asm(" NOP");
asm(" NOP");
asm(" NOP");
asm(" NOP");
Count++;
if (LastSec!=Sec)
{
LastSec=Sec;
LastLoopCount=Count;
LastSecSamples=Sec;
Count=0;
}
// OS_IDLE_LOOP()
}
}
Then look at the value of LastLoopCount
On a simple Idle app it will be around X (You need to measure X running a trivial program that just sits in OSTimeDly to see what this is)
extern volatile uint32_t LastLoopCount;
extern volatile uint32_t LastSecSampled;
uint32_t CpuFreePercentPreviousSecond()
{
if(LastSecSampled<(Sec-2)) return 0;
return 100*LastLoopCount/(MY_MEASURED_X_CONSTANT);
}
The idle task runs whenever nothing else is running, it runs all the time in a big nop loop.
so
Change the idle code from:
static void OSTaskIdle(void *data)
{
data = data;
while (1)
{
asm(" NOP");
asm(" NOP");
asm(" NOP");
asm(" NOP");
asm(" NOP");
asm(" NOP");
asm(" NOP");
asm(" NOP");
asm(" NOP");
// OS_IDLE_LOOP()
}
}
to this:
volatile uint32_t LastLoopCount;
volatile uint32_t LastSecSampled;
static void OSTaskIdle(void *data)
{
data = data;
uint32_t LastSec;
uint32_t Count;
while (1)
{
asm(" NOP");
asm(" NOP");
asm(" NOP");
asm(" NOP");
asm(" NOP");
asm(" NOP");
asm(" NOP");
asm(" NOP");
asm(" NOP");
Count++;
if (LastSec!=Sec)
{
LastSec=Sec;
LastLoopCount=Count;
LastSecSamples=Sec;
Count=0;
}
// OS_IDLE_LOOP()
}
}
Then look at the value of LastLoopCount
On a simple Idle app it will be around X (You need to measure X running a trivial program that just sits in OSTimeDly to see what this is)
extern volatile uint32_t LastLoopCount;
extern volatile uint32_t LastSecSampled;
uint32_t CpuFreePercentPreviousSecond()
{
if(LastSecSampled<(Sec-2)) return 0;
return 100*LastLoopCount/(MY_MEASURED_X_CONSTANT);
}
-
- Posts: 624
- Joined: Mon May 12, 2008 10:55 am
Re: Getting CPU statistics
I implemented your test and averaged the LastLoopCount over 30-seconds, while my app only executed OSTimeDly(TICKS_PER_SECOND).
Putting it all together, the CPU usage is around 16%. But I think that's the usage of the idle task, not my app. When I stress my app, the percentage drops by 1-2%. Therefore, isn't my app's usage really 100-16 = 84%?
Putting it all together, the CPU usage is around 16%. But I think that's the usage of the idle task, not my app. When I stress my app, the percentage drops by 1-2%. Therefore, isn't my app's usage really 100-16 = 84%?
-
- Posts: 624
- Joined: Mon May 12, 2008 10:55 am
Re: Getting CPU statistics
Regarding free memory, the diagnostic tab appears to only show the amount of free ram at compile time. If I malloc a bunch of memory, and reload the diagnostic page, the free memory reported doesn't change. I'm guessing there is no way to determine the amount of available ram memory at run-time as the memory is consumed.
Re: Getting CPU statistics
Perhaps it would be good to have this implemented in the toolkit so we don't have to overload things that might change? (just a "easy" CPU usage percentage)
Also, on MODM7, there is only the "wfi" instruction, would not having a counter before/after that in the loop increase the power significantly?
Also, on MODM7, there is only the "wfi" instruction, would not having a counter before/after that in the loop increase the power significantly?
Re: Getting CPU statistics
Perhaps, if possible, a cpu timer in front and after the "wfe", (MODM7, flash.cpp, idle task) could measure the time WFE sleeps and derive CPU usage based on that? Do we need a system timer or do the M7 have a CPU tick timer we could access for this usage?
Re: Getting CPU statistics
The M7 has a system timer, use the stopwatch function.
stopwatch.h.
stopwatch.h.
Re: Getting CPU statistics
As for fremem....
Its a little complicated...
malloc (or new) gets memory from sbrk...
When memory is returned to malloc it does not return it to sbrk....
So if you malloc 1M then free it... all future allocations will come out of that 1M until it runs out...
Then it will call sbrk....
The freemem report shows how much sbrk has left to give....
It will only ever decrease, it will never go back up if things are freed to malloc...
So I wrote this test:
while (1)
{
OSTimeDly(TICKS_PER_SECOND*5);
void * p = malloc(100000);
printf("P=%p\r\n",p);
}
And monitored freemem...
It decreases 100K every 5 seconds as it should...
(You have to reload the diagnostic page as it does not self refresh)
So the freemem reported is the minimum free one could have..
Its a little complicated...
malloc (or new) gets memory from sbrk...
When memory is returned to malloc it does not return it to sbrk....
So if you malloc 1M then free it... all future allocations will come out of that 1M until it runs out...
Then it will call sbrk....
The freemem report shows how much sbrk has left to give....
It will only ever decrease, it will never go back up if things are freed to malloc...
So I wrote this test:
while (1)
{
OSTimeDly(TICKS_PER_SECOND*5);
void * p = malloc(100000);
printf("P=%p\r\n",p);
}
And monitored freemem...
It decreases 100K every 5 seconds as it should...
(You have to reload the diagnostic page as it does not self refresh)
So the freemem reported is the minimum free one could have..