1

How much time does an Arduino Uno or Mega need to only call a function. And how does the time change if this function is inside a Class, for example inside a Library?

The same thing for a variable. How much time does a micro-controller need to read a declared variable?

How to determine this values? Is there a mathematic formula? Can we predetermine this type of delays and other similar micro-controller related delays?

  • Is this question really about how to optimize performance for a micro-controller? What are your performance goals? Why not start with high level system optimizations first. They give XN instead of N%. – Mikael Patel Aug 24 '16 at 10:15
8

It is hard to give a general answer, as it depends on the specifics of your code and on how the compiler compiles it:

How much time does an Arduino Uno or Mega need to only call a function.

This can involve a number of things:

  • the caller puts the arguments on some predefined CPU registers, unless they are already there from a previous operation (the compiler tries to optimize the code so that this happens whenever possible)
  • the caller issues the call instruction to do the actual function call
  • the callee pushes some CPU registers into the stack in order to use them without clobbering the caller's data
  • the callee does its job
  • the callee pops the previously pushed registers
  • the callee issues the ret (meaning return) instruction
  • the caller finds the return value in some CPU registers

On the Uno, the call and ret instructions cost 4 CPU cycles each (0.25 µs). On the Mega, it's 5 cycles (0.3125 µs) each. push and pop are 2 cycles each, and you need one such pair for every 8-bit register you need to save.

And how does the time change if this function is inside a Class, for example inside a Library?

The only difference is that a class method receives an extra hidden parameter called this. Except if it's a virtual method, which is more expensive because it involves some pointer dereferencing.

How much time does a micro-controller need to read a declared variable?

“Reading” generally means transferring the contents of the variable to some CPU registers. Local variable are usually allocated to CPU registers in the first place, so there is no need to read them. Global (and local static) variables are stored in RAM, and reading them takes 2 cycles per byte (e.g. 4 cycles for a 16-bit int).

How to determine this values?

Disassemble the code generated by the compiler. Then look up the instructions in the instruction set manual: it documents the number of clock cycles needed by each instruction.

  • 1
    Would add that the compiler may inline functions to allow further optimizations. Also the compiler may eliminate a variable if const, reuse value from register, etc. In these cases the time needed is zero or even negative :) – Mikael Patel Aug 23 '16 at 12:39
3

How much time does an Arduino Uno or Mega need to only call a function.

Why do you want to know? This sounds like an X-Y problem.

It will vary, depending on a lot of things.

  • The number of arguments, because the more arguments the more work involved. Plus if an argument involves copying it might invoke a copy constructor.

  • Whether or not the compiler in-lines the function. If it is in-lined (copied into the other function) then there is less work, for example the compiler doesn't need to generate call and ret instructions.

  • What the function does. The more things a function does, the more registers the compiler may have to push and then pop afterwards to save the state of registers which had useful information in them, outside the called function.

  • The size of the arguments. Longer arguments take longer to copy onto the stack, or put into registers. For example, long arguments will take longer than char arguments.


How much time does a micro-controller need to read a declared variable?

Again, it varies. It depends on the variable size, and whether or not it is already in a register. If the variable happens to be in a register at the time, you could argue it takes zero time to read it.


How to determine this values?

The sensible thing to do is to time some test code. Here's an example from another thread:

void setup ()
  {
  Serial.begin (115200);
  Serial.println ();

  unsigned long start, finish;

  start = micros ();
  for (byte i = 0; i < 100; i++)
    digitalWrite (13, HIGH);
  finish = micros ();

  Serial.print ("Time taken to do digitalWrites: ");
  Serial.println (finish - start);
  Serial.flush ();

  }  // end of setup

void loop ()
  {
  }  // end of loop

In the middle of the code there I time doing digitalWrite 100 times. By dividing the resulting output by 100, I can work out how long each digitalWrite takes.


You don't normally need to know how long, exactly, it takes to read variables, and call functions. Either your code works at an acceptable speed, or it doesn't.

Trying to answer this question on test code may give meaningless results. For example, in my test code the compiler may have in-lined the digitalWrite call. But if I use digitalWrite in many places it will no longer in-line it, which means the timing figures are now incorrect.


The Questions is how much time the millis() and micros() functions need to finish their work, so the measurement is accurate.

If that was what you wanted to know, it would have been better to ask that exact question. That saves us waffling on about copy constructors and so on.

I tested with the code below, which calls micros() and saves the results to a variable foo. I made it volatile so that the compiler wouldn't be tempted to optimize away the saving altogether (because it isn't used anywhere else).

void setup ()
  {
  pinMode (13, OUTPUT);
  PORTB = 0;
  }  // end of setup

volatile unsigned long foo;

void loop ()
  {
  PINB = bit (PB5);   // toggle D13
  foo = micros ();
  PINB = bit (PB5);   // toggle D13
  }  // end of loop

I measured 3.380 µs on my oscilloscope for the time when D13 is high. That would be 54 clock cycles. A couple (only) would be the time taken to toggle D13. Thus you can probably reckon micros() in general as taking 3.38 µs.

Changing it to call millis() instead, it only takes 1.760 µs (28 clock cycles). This is probably because all millis() does is return a variable which has already been calculated (in the timer ISR).

Test done on an Arduino Uno running at 16 MHz.

  • The Questions is how much time the millis() and micros() functions need to finish their work, so the measurement is accurate. – William Roy Aug 24 '16 at 13:25
  • You don't need to save the return value of micros() to RAM. Doing so takes 8 extra cycles. The compiler can't optimize the call away because it is not aware that micros() has no side effects. – Edgar Bonet Sep 3 '16 at 7:55
  • Well, the OP was also asking about time taken to read variables. If I needed to time some thing, I would need to get the start time, save it, and then get the end time, and subtract one from the other. – Nick Gammon Sep 4 '16 at 0:02
  • No need to save to RAM though: if you use local variables, they are likely to be allocated to CPU registers by the compiler. I tried compiling your first example and that is exactly what happened: neither start nor finish were committed to RAM. The overhead of timing the loop was 2 cycles (a couple of movw) + the cost of a call to micros(). – Edgar Bonet Sep 5 '16 at 14:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.