Understanding calculation speed of different functions

Hi all,

For a timing-critical project I am trying to understand how long it takes Arduino to carry out certain functions. One of the tests that I did involved a counter within a simple conditional statement to see how often that statement can be carried out in a second. I noticed that there is a large difference between using the 'while'-statement and the 'if'-statement. The first one seems to carry out twice as fast as the second.

The 'while'-code:

unsigned long timer = 0;
unsigned long counter = 0;

void setup() {
  Serial.begin(9600);
}

void loop() { 
  while (timer < (millis() - 1000)){
        counter++;
  }
  Serial.print("Speed of calculation: ");
  Serial.print(counter);
  Serial.println(" Hz");  
}

And the almost identical 'if'-code:

unsigned long timer = 0;
unsigned long counter = 0;

void setup() {
  Serial.begin(9600);
}

void loop() { 
  if (timer < (millis() - 1000)){
        counter++;
  }
  else {
  Serial.print("Speed of calculation: ");
  Serial.print(counter);
  Serial.println(" Hz");
  }
}

Results:
While-code: 269669 Hz;
If-code: 134835 Hz

Difference 134835 / 269669 = 0.5

Any idea why the if-statement takes twice as long?

The while stays in its loop until the end condition is met.
The if checks, performs, goes to the top of loop, checks, performs, etc.

while will appear to be stuck in the loop, the if will let other things occur.
think delay vs blink-without-delay

That's because the while loop does nothing but count until the timer expires and the if runs the entire loop() function until the timer expires. The if is slowed down by the time it takes to exit and re-enter the loop() function.

Note that you are also measuring the time it takes to call millis() and calculate if the time has expired.

Rather than running the loop for one second you could run the loop for a million counts and compare the start and end times. This would be two calls to millis() instead of 130,000 calls.

unsigned long startTime, endTime;
unsigned long counter = 0;

void setup() {
  Serial.begin(9600);
}

void loop() { 
  startTime = millis();
  while (counter < 1000000) counter++;
  endTime = millis();

  Serial.print("Speed of calculation: ");
  Serial.print(1000000000UL / (endTime - startTime));
  Serial.println(" Hz");  
}