Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

How can I measure execution time and memory usage of C implemented libraries?

Status
Not open for further replies.
Hello.

I have the task of evaluate functions of C implemented libraries that will run on embedded systems. Those libraries are implemented in .h files and then included in implementations.

I was given a FFT library implemented in C that was meant to run on Arduino. In the readme file of the library there are two charts measuring execution time, RAM and FLASH usage of each of the functions that compose the library. I need to find a way to make those measurements and see if they match with what is given in that file.

I managed to evaluate execution time using Arduino and running micros() before and after the function and then measuring the time difference and I got good results. But I still haven't found a way of measuring memory usage. I need to find a way of measuring FLASH (memory that takes the code itself) for each function and SRAM (global and local variables) also for each function. I need to find a compiler that provides a memory map, or a code to make the measurement or something similar. I know that measuring dynamic data can be tricky so by far I have just tried to use the MemoryFree library for Arduino and the information that the compiler provides but got no useful results since I need it for every function and not for the hole code and also because the mentioned library gave no useful results. I have also googled a lot but found nothing.

I really appreciate if someone know how to do that or know where can I find useful information about it.

Thanks in advance.

PS: Attached you can find the FFT library (including the readme file with the charts).
 

Attachments

  • ArduinoFFT.zip
    27.7 KB · Views: 257
The compiler gives you the used ram and flash of the program. If you can remove a single function from your library and re-compile, then you can calculate the difference in memory usage. That would be the simplest way to get a good estimate.

Other, more detailed, way is to look at the disassembly and calculate from there.
Here is an example of a function for calculating checsums.
C:
void classb_crc32_update(uint32_t *checksum, uint8_t data)
{
00000A9B  PUSH R16        Push register on stack
00000A9C  PUSH R17        Push register on stack
00000A9D  MOVW R30,R24        Copy register pair
00000A9E  MOV R24,R22        Copy register
    (*checksum) ^= (uint32_t)data;
00000A9F  LDD R20,Z+0        Load indirect with displacement
00000AA0  LDD R21,Z+1        Load indirect with displacement
00000AA1  LDD R22,Z+2        Load indirect with displacement
00000AA2  LDD R23,Z+3        Load indirect with displacement
00000AA3  EOR R20,R24        Exclusive OR
00000AA4  STD Z+0,R20        Store indirect with displacement
00000AA5  STD Z+1,R21        Store indirect with displacement
00000AA6  STD Z+2,R22        Store indirect with displacement
00000AA7  STD Z+3,R23        Store indirect with displacement
00000AA8  LDI R24,0x08        Load immediate
        if ((*checksum) & 0x01)
00000AA9  LDD R16,Z+0        Load indirect with displacement
00000AAA  LDD R17,Z+1        Load indirect with displacement
00000AAB  LDD R18,Z+2        Load indirect with displacement
00000AAC  LDD R19,Z+3        Load indirect with displacement
00000AAD  MOVW R22,R18        Copy register pair
00000AAE  MOVW R20,R16        Copy register pair
00000AAF  LSR R23        Logical shift right
00000AB0  ROR R22        Rotate right through carry
00000AB1  ROR R21        Rotate right through carry
00000AB2  ROR R20        Rotate right through carry
00000AB3  SBRS R16,0        Skip if bit in register set
00000AB4  RJMP PC+0x0009        Relative jump
            (*checksum) = ((*checksum) >> 1) ^ CRC32_POLYNOMIAL;
00000AB5  LDI R25,0x20        Load immediate
00000AB6  EOR R20,R25        Exclusive OR
00000AB7  LDI R25,0x83        Load immediate
00000AB8  EOR R21,R25        Exclusive OR
00000AB9  LDI R25,0xB8        Load immediate
00000ABA  EOR R22,R25        Exclusive OR
00000ABB  LDI R25,0xED        Load immediate
00000ABC  EOR R23,R25        Exclusive OR
            (*checksum) >>= 1;
00000ABD  STD Z+0,R20        Store indirect with displacement
00000ABE  STD Z+1,R21        Store indirect with displacement
00000ABF  STD Z+2,R22        Store indirect with displacement
00000AC0  STD Z+3,R23        Store indirect with displacement
00000AC1  SUBI R24,0x01        Subtract immediate
    for (uint8_t i = 8; i > 0; --i)
00000AC2  BRNE PC-0x19        Branch if not equal
}
00000AC3  POP R17        Pop register from stack
00000AC4  POP R16        Pop register from stack
00000AC5  RET         Subroutine return
You can see that the entry point of the function is memory location 00000A9B.
And return instruction from the function is at 00000AC5.
So, the function takes (AC5-A9B + 1)*2 = 86 bytes of memory.
Functions usually call other functions, so at this point it is up to decide how detailed memory map you want to create. Do you include subroutines or not.

RAM memory usage for global and static variables is easy. Just add up the sizes of these variables. If the variable is a static variable inside a function, then you can be almost sure that the variable is used only by that function. Global variables are usually used by many functions. So, it is up to you to decide how detailed memory map you want to create.
 
Last edited:
When I got my Arduino I was surprised that when you compiled a program it did not have a directory where you could easily view the assembler file and make a copy of the hex file to load in future. It took me a long time to find out how to find the assembler file. I found the information here. https://ucexperiment.wordpress.com/...-language-listing-of-compiled-sketch-windows/

Les.
The idea of Arduino is to hide all that "technical" and "advanced" stuff from the user. I would switch to Atmel Studio.
I have not tried to compile sketch-code with it, but there are plug-ins. https://www.visualmicro.com/page/Arduino-for-Atmel-Studio.aspx
 
Actually there is also a file .map (when you compile with Atmel Studio), which is a linker address map. It shows you the sizes of all functions etc.. and more.

here are few lines from one of my projects:
Code:
*(.text.*)
.text.pp_interpolate_ntc
                0x000003a8      0x18e analyzer.o
.text.pp_tmp_calculate_obj_temp
                0x00000536      0x282 analyzer.o
.text.tmp_calculate_obj_temp2
                0x000007b8      0x3ee analyzer.o
.text.preprocess_meas_data
                0x00000ba6       0xf0 analyzer.o

You can see directly that the size of function "interpolate_ntc" is 0x18e bytes (or 16 bit words.. not sure). It also lists all variables.
 
Last edited:
Hi misterT,
I find the "C" part the hard part. I find the assembler part easy to understand.

Les.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top