Speed Test

I recently bought an Arduino Due, and I worked up this code to compare the speeds of Due and Uno.

#include <stdint.h>

void setup() {
  
  /*
  Results
  My Due = 7425986u = 7427m
  My Uno = 24591260u = 24591m
  */
  
  // put your setup code here, to run once:
  pinMode(13, OUTPUT);
  
  Serial.begin(115200);
  while(!Serial);
  Serial.println("Start");
  
  float a = 0.2;
  float b = 0.3;
  /* 0 to 4,294,967,295 */
  uint32_t startMicros = micros();
  uint32_t startMillis = millis();
  for(uint32_t i=0;i<10000;i++){
    for(uint32_t j=0;j<100;j++){
      a = b = (digitalRead(2)+2);
      b = a*(digitalRead(2)+1);
      a = b*(digitalRead(2)-1);
      a = a*1.5*(digitalRead(2)-5);
      b = b*1.5+(digitalRead(2)-200);
      a = b*a;
      if(a>2.3 && b<0.5){
        digitalWrite(13, HIGH);
      }else{
        digitalWrite(13, HIGH);
      }
    }
  }
  Serial.print("Micros = ");Serial.println(micros()-startMicros);
  Serial.print("Millis = ");Serial.println(millis()-startMillis);
  Serial.println("End");
  
}

void loop() {
  // put your main code here, to run repeatedly:
  digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(100);              // wait for a second
  digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
  delay(100); 
}

Given the clock speed and 32 bit controller of the due. I has hoping for a difference of 84/16 * 4 = 21 Times. But my experiment returned that my Due is only 3.3 times faster than my uno.

Am I missing something here? I am starting to suspect that I have received a fake Due. Can anybody post their result by running this code.

The slowness is probably in digitalRead and digitalWrite.

I just ran it here on a Teensy 3.1.

Start
Micros = 1117377
Millis = 1117
End

Then I tried changing all the digitalRead and digitalWrite to digitalReadFast and digitalWriteFast. The result with the fast functons:

Start
Micros = 188206
Millis = 188
End

But that seems too fast to be true. So I tried another run, with two Serial.println() added after the test, to print the values of a and b.

Start
Micros = 11313829
Millis = 11314
End
-2955.00
-197.00

So it seems the compiler “knows” the values of a and b aren’t ever used, so it’s not bothering to actually perform most of the calculations.

Here’s the full modified code. I’d recommend running this on both your boards.

#include <stdint.h>

void setup() {
  
  /*
  Results
  My Due = 7425986u = 7427m
  My Uno = 24591260u = 24591m
  */
  
  // put your setup code here, to run once:
  pinMode(13, OUTPUT);
  pinMode(2, INPUT);
  
  Serial.begin(115200);
  while(!Serial);
  Serial.println("Start");
  
  float a = 0.2;
  float b = 0.3;
  /* 0 to 4,294,967,295 */
  uint32_t startMicros = micros();
  uint32_t startMillis = millis();
  for(uint32_t i=0;i<10000;i++){
    for(uint32_t j=0;j<100;j++){
      a = b = (digitalReadFast(2)+2);
      b = a*(digitalReadFast(2)+1);
      a = b*(digitalReadFast(2)-1);
      a = a*1.5*(digitalReadFast(2)-5);
      b = b*1.5+(digitalReadFast(2)-200);
      a = b*a;
      if(a>2.3 && b<0.5){
        digitalWriteFast(13, HIGH);
      }else{
        digitalWriteFast(13, HIGH);
      }
    }
  }
  Serial.print("Micros = ");Serial.println(micros()-startMicros);
  Serial.print("Millis = ");Serial.println(millis()-startMillis);
  Serial.println("End");
  Serial.println(a);
  Serial.println(b);
}

void loop() {
  // put your main code here, to run repeatedly:
  digitalWriteFast(13, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(100);              // wait for a second
  digitalWriteFast(13, LOW);    // turn the LED off by making the voltage LOW
  delay(100); 
}

Normal Arduino boards don’t have digitalWriteFast built in, so you’ll have to find the library that adds it, or just change back to normal digitalRead and digitalWrite.

Here is the test run one more time on Teensy 3.1, with the slower digitalRead and digitalWrite

Start
Micros = 12483028
Millis = 12483
End
-2955.00
-197.00

Measuring performance is tricky business. It’s easy to end up with wrong results, because the compiler is crafty about optimizing away unnecessary work, and because functions you think would be fast can actually end up obscuring the actual CPU speed.

The 32-bit words used by the Due might be 4 times faster than the Uno 8 bits but only for calculations. Logic code like the if and the loop won’t get the same speedup.

Try something with an integer division in it. This is really slow on the Uno. Sometimes the Uno’s floating point division is faster than its integers. The Due supposedly has hardware division.

Multiplying by 1.5 in your code will force a floating point conversion. I don’t know if this is a slow function on the Due.