Microcontroller I/O & ADC Benchmarks

While trying to determine the most suitable MCU for a project that needs fast analogue read I decided to knock up a quick bench-test sketch and run it on some of the various MCU's I have kicking around.
Hope the info is helpful and maybe others can add new MCU's or tests.

Arduino UNO I/O Speed Tests Over 50000 Iterations.
Digital Pin Write Takes About 4.50 Microseconds.
Digital Pin Read Takes About 4.78 Microseconds.
Analogue Pin Read Takes About 112.00 Microseconds.

Arduino Mega I/O Speed Tests Over 50000 Iterations.
Digital Pin Write Takes About 6.50 Microseconds.
Digital Pin Read Takes About 6.35 Microseconds.
Analogue Pin Read Takes About 112.01 Microseconds.

Arduino Due I/O Speed Tests Over 50000 Iterations.
Digital Pin Write Takes About 2.00 Microseconds.
Digital Pin Read Takes About 1.11 Microseconds.
Analogue Pin Read Takes About 3.30 Microseconds.

Teensy 3.1 @ 24MHz I/O Speed Tests Over 50000 Iterations.
Digital Pin Write Takes About 1.00 Microseconds.
Digital Pin Read Takes About 0.75 Microseconds.
Analogue Pin Read Takes About 12.88 Microseconds.

Teensy 3.1 @ 48MHz I/O Speed Tests Over 50000 Iterations.
Digital Pin Write Takes About 0.50 Microseconds.
Digital Pin Read Takes About 0.38 Microseconds.
Analogue Pin Read Takes About 10.14 Microseconds.

Teensy 3.1 @ 72MHz I/O Speed Tests Over 50000 Iterations.
Digital Pin Write Takes About 0.00 Microseconds.
Digital Pin Read Takes About 0.25 Microseconds.
Analogue Pin Read Takes About 7.59 Microseconds.

Teensy 3.1 @ 96MHz I/O Speed Tests Over 50000 Iterations.
Digital Pin Write Takes About 0.00 Microseconds.
Digital Pin Read Takes About 0.19 Microseconds.
Analogue Pin Read Takes About 10.37 Microseconds.

Fubarino Mini (dev) I/O Speed Tests Over 50000 Iterations.
Digital Pin Write Takes About 1.50 Microseconds.
Digital Pin Read Takes About 0.85 Microseconds.
Analogue Pin Read Takes About 8.77 Microseconds.

Nucleo STM32F401 I/O Speed Tests Over 1000000 Iterations.
Digital Pin Write Takes About 0.1668 Microseconds.
Digital Pin Read Takes About 0.1788 Microseconds.
Analogue Pin Read Takes About 3.4917 Microseconds.

Arduino Zero I/O Speed Tests Over 50000 Iterations. Compiled Using Arduino IDE v1.8.7
Digital Pin Write Takes About 1.6234 Microseconds.
Digital Pin Read Takes About 1.0264 Microseconds.
Analogue Pin Read Takes About 423.2541 Microseconds.

ESP8266 Wemos D1 Mini I/O Speed Tests Over 50000 Iterations. Compiled Using Arduino IDE v1.8.9 and 2.50 Core
Digital Pin Write Takes About 0.9627 Microseconds.
Digital Pin Read Takes About 0.5881 Microseconds.
Analogue Pin Read Takes About 153.9349 Microseconds.

ESP32 DoIt ESP32 Devkit V1 (80MHz) I/O Speed Tests Over 50000 Iterations. Compiled Using Arduino IDE v1.8.9 and 1.0.2 Core
Digital Pin Write Takes About 0.1199 Microseconds.
Digital Pin Read Takes About 0.1642 Microseconds.
Analogue Pin Read Takes About 10.3027 Microseconds.

Benchmark_IO.ino (2.07 KB)

1 Like

I have created another sketch for the AVR (UNO) that runs the ADC test using different pre-scaler settings.

The results on an UNO

Arduino UNO I/O Speed Tests Over 1000 Iterations.
ADPS2 Analogue Pin Read Takes About 4.96 Microseconds.
ADPS4 Analogue Pin Read Takes About 6.52 Microseconds.
ADPS8 Analogue Pin Read Takes About 10.04 Microseconds.
ADPS16 Analogue Pin Read Takes About 17.06 Microseconds.
ADPS32 Analogue Pin Read Takes About 30.12 Microseconds.
ADPS64 Analogue Pin Read Takes About 56.10 Microseconds.
ADPS128 Analogue Pin Read Takes About 112.00 Microseconds.

AVR_ADC_Speed_Test.ino (1.28 KB)

Made the topic sticky because imho it is very informative.

athough some numbers make me think there is a loss of precision in the math somewhere.

Teensy 3.1 @ 48MHz I/O Speed Tests Over 50000 Iterations.
Digital Pin Write Takes About 0.50 Microseconds.
Digital Pin Read Takes About 0.38 Microseconds.
Analogue Pin Read Takes About 10.14 Microseconds.

Teensy 3.1 @ 72MHz I/O Speed Tests Over 50000 Iterations.
Digital Pin Write Takes About 0.00 Microseconds. <<<<<<<<< expected something like 0.33 here
Digital Pin Read Takes About 0.25 Microseconds.
Analogue Pin Read Takes About 7.59 Microseconds.

1 Like

The Teensy is fast! When the Tre and Zero come out, they should be benchmarked as well. (Not the 32u4 on the Tre, the Sitara.)

robtillaart:
Made the topic sticky because imho it is very informative.

athough some numbers make me think there is a loss of precision in the math somewhere.

Yes there does appear to be some loss of precision, I should maybe have printed to 4 decimal places instead of the default 2 but I have got the results I need for analogue so will probably not alter the code and re-run the tests.
I have added a Nucleo to the results and I had to up the precision there to see anything.

EDIT: I have attached a slightly modified version that displays result to 4 decimal places instead of 2.

Benchmark_IO.ino (2.21 KB)

Nucleo STM32F401 I/O Speed Tests Over 1000000 Iterations.
Digital Pin Write Takes About 0.1668 Microseconds.
Digital Pin Read Takes About 0.1788 Microseconds.
Analogue Pin Read Takes About 3.4917 Microseconds.

Using what SW? I didn't think the Nucleo supported Arduino libraries yet.

westfw:
Using what SW? I didn't think the Nucleo supported Arduino libraries yet.

The Nucleo is not supported yet but some other STM32 variants have Arduino cores here.
I converted the Benchmark sketch to suit mbed compiler.

#include "mbed.h"

#define targetBoard "Nucleo STM32F401"

AnalogIn analoguePin(A0);
DigitalIn digitalPinIn(USER_BUTTON);
DigitalOut digitalPinOut(LED1);

const unsigned int loopCount = 1000000;
Timer timeX;
Serial pc(USBTX, USBRX); // tx, rx

int main()
{
    unsigned int x;
    double ar;
    
    pc.printf(" *****************\n\n\n");
    while(1) {
        pc.printf(targetBoard);
        pc.printf(" I/O Speed Tests Over ");
        pc.printf("%d Iterations.\n", loopCount);
        wait_ms(1000);

        // Digital Write
        timeX.reset();
        timeX.start();
        for (x = 0; x < loopCount; x++) {
            digitalPinOut = 1;
            digitalPinOut = 0;
        }
        timeX.stop();
        pc.printf("Digital Pin Write Takes About %.4f Microseconds.\n", (double)timeX.read_us() / loopCount / 2.0 );
        wait_ms(1000);

        // Digital Read
        timeX.reset();
        timeX.start();
        for (x = 0; x < loopCount; x++) {
            ar = digitalPinIn;
        }
        timeX.stop();
        pc.printf("Digital Pin Read  Takes About %.4f Microseconds.\n", (double)timeX.read_us() / loopCount );
        wait_ms(1000);

        // Analogue
        timeX.reset();
        timeX.start();
        for (x = 0; x < loopCount; x++) {
            ar = analoguePin.read();
        }
        timeX.stop();
        pc.printf("Analogue Pin Read Takes About %.4f Microseconds.\n\n", (double)timeX.read_us() / loopCount );
        wait_ms(2000);
    }
}

Arduino UNO I/O Speed Tests Over 50000 Iterations.
Digital Pin Write Takes About → 4.50 ← Microseconds.
Digital Pin Read Takes About → 4.78 ← Microseconds.

Arduino Mega I/O Speed Tests Over 50000 Iterations.
Digital Pin Write Takes About → 6.50 ← Microseconds.
Digital Pin Read Takes About → 6.35 ← Microseconds.

Something wrong with your Mega? Was it running at 12 MHz? Had too much beer the night before the test?

(The question is rhetorical; meant to goad you into investigating. I know why there is a difference.)

I had noticed the Mega seemed slower at digital I/O but never bothered to investigate as it was analogue I was interested in. Maybe it's due to core differences in how pins are read/written as pin 9 is PWM on both UNO & MEGA and don't seem to serve as multi function pins (I2C, SPI, UART etc.) that may slow things down. The only other possibility I can think of is interrupt overheads as I don't disable them for testing but analogue read is the same between both UNO & Mega.

Ideally the test sketch should do all the I/O pins and maybe include analogWrite() on supported pins but it served the purpose I needed. Maybe I or someone else can do comprehensive tests at some point.

Riva:
Ideally the test sketch should do all the I/O pins and maybe include analogWrite() on supported pins.

Starting to quote myself now LOL
Below is a new benchmark sketch that does test all the pins and the results obtained from the 3 boards I have configured and tested it for. Due to the added complexity of doing analogue read/write on boards with not consecutive analogue pins the sketch needs any new board types added & configured in the defines.

Benchmark V3.0 05-June-2015
Arduino UNO I/O Speed Tests Over 1000 Iterations. Compiled Using Arduino IDE v1.0.6

Digital Pin Read / Write Times In Microseconds.
 0 4.1520 / 4.1200
 1 4.1520 / 4.1200
 2 4.0880 / 4.1200
 3 4.9720 / 5.0020
 4 4.0880 / 4.1200
 5 4.9720 / 4.9980
 6 4.9080 / 4.9360
 7 4.0920 / 4.1200
 8 4.0920 / 4.1200
 9 4.7760 / 4.8140
 10 5.2840 / 5.3140
 11 4.9720 / 5.0000
 12 4.0920 / 4.1200
 13 4.0920 / 4.1200
 14 4.0880 / 4.1200
 15 4.0920 / 4.1200
 16 4.0920 / 4.1240
 17 4.0920 / 4.1200
 18 4.0880 / 4.1200
 19 4.0920 / 4.1200

Analogue Pin Read Times In Microseconds.
 A0 112.0960
 A1 112.0080
 A2 112.0080
 A3 112.0080
 A4 112.0080
 A5 112.0080

Analogue Pin Write Times In Microseconds.
 3 8.5120
 5 8.3240
 6 8.1400
 9 8.2000
 10 8.8320
 11 8.3880


Benchmark V3.0 05-June-2015
Arduino Leonardo I/O Speed Tests Over 1000 Iterations. Compiled Using Arduino IDE v1.0.6

Digital Pin Read / Write Times In Microseconds.
 0 4.5880 / 4.8740
 1 4.5960 / 4.8760
 2 4.5880 / 4.8720
 3 5.7280 / 6.0060
 4 4.5880 / 4.8760
 5 5.7280 / 6.0040
 6 6.4160 / 6.6960
 7 4.5960 / 4.8760
 8 4.5880 / 4.8760
 9 6.2920 / 6.5680
 10 6.3560 / 6.6340
 11 6.2280 / 6.5120
 12 4.5920 / 4.8760
 13 6.0880 / 6.3200
 14 4.5960 / 4.8760
 15 4.5960 / 4.8720
 16 4.5960 / 4.8760
 17 4.6560 / 4.8720
 18 4.5880 / 4.8760
 19 4.5960 / 4.8760

Analogue Pin Read Times In Microseconds.
 A0 112.1080
 A1 112.0040
 A2 112.0680
 A3 114.4760
 A4 112.5000
 A5 112.1400
 A6 112.1480
 A7 112.1640
 A8 112.1440
 A9 112.1320
 A10 112.1520
 A11 112.1480

Analogue Pin Write Times In Microseconds.
 3 8.2400
 5 8.3040
 6 9.4960
 9 8.8720
 10 9.1240
 11 8.6200
 12 13.0920
 13 8.8720


Benchmark V3.0 05-June-2015
Arduino MEGA2560 I/O Speed Tests Over 1000 Iterations. Compiled Using Arduino IDE v1.0.6

Digital Pin Read / Write Times In Microseconds.
 0 4.7200 / 4.9360
 1 4.7160 / 4.9400
 2 5.9120 / 6.1960
 3 6.6080 / 6.8860
 4 6.1640 / 6.4460
 5 6.6040 / 6.8900
 6 6.5480 / 6.8240
 7 6.6640 / 6.9500
 8 6.1640 / 6.4440
 9 6.3520 / 6.6360
 10 6.8560 / 7.1400
 11 6.5480 / 6.8260
 12 6.0400 / 6.3200
 13 6.7080 / 6.9520
 14 4.6600 / 4.9360
 15 4.6520 / 4.9380
 16 4.6600 / 4.9380
 17 4.6520 / 4.9340
 18 4.6520 / 4.9360
 19 4.6600 / 4.9400
 20 4.7160 / 4.9400
 21 4.7240 / 4.9360
 22 4.6600 / 4.9380
 23 4.6560 / 4.9380
 24 4.6600 / 4.9360
 25 4.6520 / 4.9400
 26 4.6560 / 4.9400
 27 4.6520 / 4.9360
 28 4.6520 / 4.9380
 29 4.6600 / 4.9380
 30 4.6520 / 4.9360
 31 4.6560 / 4.9360
 32 4.6520 / 4.9400
 33 4.6600 / 4.9400
 34 4.6600 / 4.9360
 35 4.6520 / 4.9400
 36 4.6600 / 4.9400
 37 4.6520 / 4.9360
 38 4.6560 / 4.9380
 39 4.6600 / 4.9380
 40 4.6560 / 4.9340
 41 4.6600 / 4.9380
 42 4.6520 / 4.9380
 43 4.6560 / 4.9360
 44 6.7360 / 7.0100
 45 6.5400 / 6.8260
 46 7.1080 / 7.3880
 47 4.6600 / 4.9380
 48 4.6560 / 4.9360
 49 4.6600 / 4.9360
 50 4.6520 / 4.9400
 51 4.6560 / 4.9380
 52 4.6520 / 4.9360
 53 4.6520 / 4.9380

Analogue Pin Read Times In Microseconds.
 A0 112.1080
 A1 112.0040
 A2 112.0040
 A3 112.0040
 A4 112.0040
 A5 112.0040
 A6 112.0040
 A7 112.0040
 A8 112.0040
 A9 112.0040
 A10 112.0040
 A11 112.0040
 A12 112.0040
 A13 112.0040
 A14 112.0080
 A15 112.0040

Analogue Pin Write Times In Microseconds.
 2 8.3960
 3 9.3400
 4 8.5880
 5 9.2160
 6 9.4000
 7 9.2760
 8 8.7760
 9 8.9000
 10 9.3400
 11 9.0240
 12 8.6440
 13 8.9680
 44 9.3400
 45 9.1520
 46 9.5920

Benchmark_IO_NEW.ino (3.99 KB)

Yet another test. This time to determine accuracy & jitter while reading an analogue pin at different pre-scale ADC speeds.

First the test using a 10K trimpot connected between 5V & GND with the wiper set to 3.3V

Default ADCSRA = 10010111
Arduino MEGA ADC Accuracy Tests Over 500 Iterations.

ADPS2 (ADCSRA = 10010001)
 Baseline Reading: 768 Rolling Average: 768
 Maximum Reading: 768 Minimum Reading: 768 Maximum Jitter: 0

ADPS4 (ADCSRA = 10010010)
 Baseline Reading: 671 Rolling Average: 671
 Maximum Reading: 671 Minimum Reading: 671 Maximum Jitter: 0

ADPS8 (ADCSRA = 10010011)
 Baseline Reading: 675 Rolling Average: 675
 Maximum Reading: 675 Minimum Reading: 675 Maximum Jitter: 0

ADPS16 (ADCSRA = 10010100)
 Baseline Reading: 675 Rolling Average: 675
 Maximum Reading: 676 Minimum Reading: 675 Maximum Jitter: 1

ADPS32 (ADCSRA = 10010101)
 Baseline Reading: 675 Rolling Average: 675
 Maximum Reading: 676 Minimum Reading: 675 Maximum Jitter: 1

ADPS64 (ADCSRA = 10010110)
 Baseline Reading: 676 Rolling Average: 675
 Maximum Reading: 676 Minimum Reading: 675 Maximum Jitter: 1

ADPS128 (ADCSRA = 10010111)
 Baseline Reading: 675 Rolling Average: 675
 Maximum Reading: 676 Minimum Reading: 675 Maximum Jitter: 1

All results are pretty close to expected reading apart from the very fastest ADC read speed.

Second test is a bit pointless as I just left the pin floating but it's interesting (to me) that all subsequent reads after the initial baseline read are lower and generally the slower the ADC the more jitter.

Default ADCSRA = 10010111
Arduino MEGA ADC Accuracy Tests Over 500 Iterations.

ADPS2 (ADCSRA = 10010001)
 Baseline Reading: 560 Rolling Average: 574
 Maximum Reading: 575 Minimum Reading: 560 Maximum Jitter: 15

ADPS4 (ADCSRA = 10010010)
 Baseline Reading: 572 Rolling Average: 572
 Maximum Reading: 572 Minimum Reading: 572 Maximum Jitter: 0

ADPS8 (ADCSRA = 10010011)
 Baseline Reading: 568 Rolling Average: 568
 Maximum Reading: 568 Minimum Reading: 568 Maximum Jitter: 0

ADPS16 (ADCSRA = 10010100)
 Baseline Reading: 563 Rolling Average: 560
 Maximum Reading: 563 Minimum Reading: 560 Maximum Jitter: 3

ADPS32 (ADCSRA = 10010101)
 Baseline Reading: 559 Rolling Average: 509
 Maximum Reading: 559 Minimum Reading: 509 Maximum Jitter: 50

ADPS64 (ADCSRA = 10010110)
 Baseline Reading: 537 Rolling Average: 455
 Maximum Reading: 537 Minimum Reading: 455 Maximum Jitter: 82

ADPS128 (ADCSRA = 10010111)
 Baseline Reading: 514 Rolling Average: 426
 Maximum Reading: 514 Minimum Reading: 426 Maximum Jitter: 88

AVR_ADC_Accuracy_Test.ino (2.15 KB)

here's a benchmark test, admittedly just about Mega and Due, but some other 3rd party MCUs additionally, performing different low- and high-level computing tests for integer, floats, binay shift, array sort, matrices, and much more, maybe some one may find it useful:

Couple of comments:

  1. Analog Front ends are not created equal. Most AVRs are lucky to get maybe 8-9 ENOB. The Teensy 3.x series offers up to 12 bit performance in single-channel mode, 13 in differential mode. The datasheet from Freescale may promise higher resolutions under some very specific circumstances, but you are unlikely to create them (chip in sleep mode, beautiful signal presentation, etc.). In other words, the vendor promises 16 bits, the real-life performance is 12-13 bits.

  2. The test above does not seem to cover the varying set of resolutions that the Teensy can use. Teensy 3.x units can perform faster ADC conversions @ 10 bits than at 12, for example. If comparing to an UNO, you should select 10 bits as the closest thing to an apples-apples comparison, even if the performance of the ADC is unlikely to be similar re: ENOB.

  3. For the Teensy, I'd suggest using the Pedevide ADC library. You can achieve much higher speeds if reads are done sequentially / continuous. This is especially true if you correct for default settings such as the averaging, resolution, etc. The Pedevide library also gives relatively painless access to differential-mode reads and simultaneous reads by the two ADCs in the Teensy 3.1 and 3.2.

  4. The Teensy also offers varying lengths of ADC acquisition and conversion time. These can vary depending on your needs, such as source impedance. You can really speed things up if you have a low impedance source or a buffer. Pedevides library gives access to all that.

  5. The AVR series doesn't offer a PGA the way Teensy 3.x does. That can be very handy. Early AVRs like the 328P allow ADC reads at up to 5V. The Teensy 3.x and LC series are limited to 3.3V max. input. While many sensors out there have 3.3V compatible versions, some legacy units do not (and vice-versa).

  6. If you have two channels to read into, you can double the sampling speed by making use of the second ADC in a Teensy 3.1 or 3.2.

  7. For situations where the pin does not have to be reconfigured, try using digitalReadFast(). It significantly speeds up digital reads by dropping some of the setup stuff that is not needed if the pinmode is not changing. Not sure if UNO supports digitalReadFast...

Though I have a Teensy 3.1 I think this is probably the only real thing I had ever done using it so am not familiar with it enough to do detailed tests (I find the documentation on extra commands/features hard to find for Teensy, it could do with a proper reference page like for Arduino - but better) . The initial test program from #0 worked on all but the ST chip so the speed comparisons are what you would expect under normal programming.

If you can write a benchmark for the Teensy that uses standard system commands/libraries (or even hitting the hardware direct) then that would be a great addition to this post and probably the Teensy forum as well.

Hi Riva,

The Pedevide ADC library is considered the standard ADC library for Teensy. Users are extremely unlikely to get at ADC features such as differential-mode reads unless they delve into specific registers and enjoying the cryptic (at best!) Freescale datasheets re: how to program the thing.

The Pedevide ADC library is hosted on Github and is installed as part of the Teensyduino package. Thus, if you have a relatively recent sample of the Teensyduino install, you should find it, along with lots of examples. Updating your test is as simple as including the Pedevide library and then using the library commands to do the sequential reads, and so on.

Is this a fair comparison? The answer of course is yes and no. The library enables things like sequential reads that for whatever reason the Arduino IDE does not support using standard commands. Ditto for digitalReadFast, etc. These sorts of standard commands for Teensy are not necessarily part of the the usual Arduino universe thanks to decisions by the higher-ups here. I can see their motivation (keep it simple) but that can get in the way of maximum performance.

Additionally, you need to specify carefully what your source is. For example, the marketing department at Freescale assumes a 8-Ohm source, external caps on the inputs, etc. I presume that Atmel has similar sets of recommendations on how to optimize the input stages.

Here are some comments from Pedevide in the ADC library with benchmarks for the LC and 3.x series that may be of interest. Note how the Teensy 3.x series can achieve 'legal' sampling speeds of 500kHz, assuming you have a very good signal source. Under default circumstances (i.e. 10bit ADC, 4x oversampling, MED conversion speed) the benchmarks indicate about 17us per conversion. Digital "fast" reads and writes go into the Megahertz range. If there is interest, I can try and dig those up also.

RESULTS OF THE TEST Teensy 3.x
Measure continuously a voltage divider.
Measurement pin A9 (23). Clock speed 96 Mhz, bus speed 48 MHz.

 Using ADC_LOW_SPEED (same as ADC_VERY_LOW_SPEED) for sampling and conversion speeds
ADC resolution     Measurement frequency           Num. averages
    16  bits             81 kHz                          1
    12  bits             94 kHz                          1
    10  bits             94 kHz                          1
     8  bits            103 kHz                          1

    16  bits            2.5 kHz                          32
    12  bits            2.9 kHz                          32
    10  bits            2.9 kHz                          32
     8  bits            3.2 kHz                          32


 Using ADC_MED_SPEED for sampling and conversion speeds
ADC resolution     Measurement frequency           Num. averages
    16  bits           193 kHz                         1
    12  bits           231 kHz                         1
    10  bits           231 kHz                         1
     8  bits           261 kHz                         1
    10  bits            58 kHz                         4 (default settings) corresponds to about 17.24 us

 Using ADC_HIGH_SPEED (same as ADC_HIGH_SPEED_16BITS) for sampling and conversion speeds
ADC resolution     Measurement frequency           Num. averages
    16  bits           414 kHz                         1
    12  bits           500 kHz                         1
    10  bits           500 kHz                         1
     8  bits           571 kHz                         1
     8  bits           308 kHz                         1 ADC_VERY_LOW_SPEED sampling
     8  bits           387 kHz                         1 ADC_LOW_SPEED sampling
     8  bits           480 kHz                         1 ADC_MED_SPEED sampling
     8  bits           632 kHz                         1 ADC_VERY_HIGH_SPEED sampling

Using ADC_VERY_HIGH_SPEED for sampling and conversion speeds. This conversion speed is over the limit of the specs! (speed=24MHz, limit = 18 MHz for res<16 and 12 for res=16)
ADC resolution     Measurement frequency           Num. averages
    16  bits           888 kHz                          1
    12  bits          1090 kHz                          1
    10  bits          1090 kHz                          1
     8  bits          1262 kHz                          1

At 96 Mhz (bus at 48 MHz), 632 KHz is the fastest we can do within the specs, and only if the sample's impedance is low enough.

RESULTS OF THE TEST Teensy LC
Measure continuously a voltage divider.
Measurement pin A9 (23). Clock speed 48 Mhz, bus speed 24 MHz.

Using ADC_VERY_LOW_SPEED for sampling and conversion speeds
ADC resolution     Measurement frequency           Num. averages
    16  bits           33.3 kHz                         1
    12  bits           37.5 kHz                         1
    10  bits           37.5 kHz                         1
     8  bits           40.5 kHz                         1

    16  bits            1.04 kHz                       32
    12  bits            1.2 kHz                        32
    10  bits            1.2 kHz                        32
     8  bits            1.3 kHz                        32

ADC_LOW_SPEED, ADC_MED_SPEED, ADC_HIGH_SPEED_16BITS, ADC_HIGH_SPEED and ADC_VERY_HIGH_SPEED are the same for Teensy 3.x and LC, except for a very small amount that depends on the bus speed and not on the ADC clock (which is the same for those speeds). This difference corresponds to 5 bus clock cycles, which is about 0.1 us.

For 8 bits resolution, 1 average, ADC_MED_SPEED sampling speed the measurement frequencies for the different ADACK are:
 ADC_ADACK_2_4       106.8 kHz
 ADC_ADACK_4_0       162.6 kHz
 ADC_ADACK_5_2       235.1 kHz
 ADC_ADACK_6_2       263.3 kHz
 
For Teensy 3.x the results are similar but not identical for two reasons: the bus clock plays a small role in the total time and the frequency of this ADACK clock is acually quite variable, the values are the typical ones, but in the electrical datasheet it says that they can range from +-50% their values aproximately, so every Teensy can have different frequencies.

hi.

i did also make a sketch to benchmark the IO/analog speed. on a DUE

here are the results:

Digital IO results
Pin.no / DigitalWrite / WriteReg / DigitalRead / ReadReg / PWM
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Pin 0|| Pin 1|| Pin 2|| Pin 3|| Pin 4|| Pin 5|| Pin 6|| Pin 7|| Pin 8|| Pin 9|| Pin10|| Pin11|| Pin12|| Pin13|| Pin14|| Pin15|| Pin16|| Pin17|| Pin18|| Pin19|| Pin20|| Pin21|| Pin22|| Pin23|| Pin24|| Pin25|| Pin26|| Pin27|| Pin28|| Pin29|| Pin30|| Pin31|| Pin32|| Pin33|| Pin34|| Pin35|| Pin36|| Pin37|| Pin38|| Pin39|| Pin40|| Pin41|| Pin42|| Pin43|| Pin44|| Pin45|| Pin46|| Pin47|| Pin48|| Pin49|| Pin50|| Pin51|| Pin52|| Pin53|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 1.23 || 1.15 || 1.40 || 1.35 || 1.35 || 1.27 || 1.40 || 1.35 || 1.35 || 1.27 || 1.40 || 1.35 || 1.35 || 1.27 || 1.28 || 1.23 || 1.23 || 1.15 || 1.28 || 1.23 || 1.35 || 1.27 || 1.40 || 1.35 || 1.35 || 1.27 || 1.40 || 1.35 || 1.35 || 1.27 || 1.40 || 1.35 || 1.35 || 1.27 || 1.40 || 1.35 || 1.35 || 1.27 || 1.40 || 1.35 || 1.35 || 1.27 || 1.40 || 1.35 || 1.35 || 1.27 || 1.40 || 1.35 || 1.35 || 1.27 || 1.40 || 1.35 || 1.35 || 1.15 |
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 |
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 1.09 || 1.04 || 1.13 || 1.08 || 1.08 || 1.04 || 1.13 || 1.08 || 1.08 || 1.04 || 1.13 || 1.08 || 1.08 || 1.04 || 1.13 || 1.08 || 1.08 || 1.04 || 1.13 || 1.08 || 1.08 || 1.04 || 1.13 || 1.08 || 1.08 || 1.04 || 1.13 || 1.08 || 1.08 || 1.04 || 1.13 || 1.08 || 1.08 || 1.04 || 1.13 || 1.08 || 1.08 || 1.04 || 1.13 || 1.08 || 1.08 || 1.04 || 1.13 || 1.08 || 1.08 || 1.04 || 1.13 || 1.08 || 1.08 || 1.04 || 1.13 || 1.08 || 1.08 || 1.04 |
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 0.14 || 0.14 || 0.13 || 0.14 || 0.13 || 0.14 || 0.14 || 0.14 || 0.13 || 0.13 || 0.13 || 0.13 || 0.14 || 0.13 || 0.14 || 0.13 || 0.13 || 0.14 || 0.13 || 0.14 || 0.13 || 0.13 || 0.14 || 0.13 || 0.14 || 0.13 || 0.13 || 0.14 || 0.13 || 0.14 || 0.13 || 0.13 || 0.14 || 0.13 || 0.14 || 0.13 || 0.13 || 0.14 || 0.13 || 0.14 || 0.13 || 0.13 || 0.14 || 0.13 || 0.14 || 0.13 || 0.13 || 0.14 || 0.13 || 0.14 || 0.13 || 0.13 || 0.14 || 0.13 |
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 3.92 || 3.91 || 3.84 || 3.91 || 2.76 || 2.76 || 2.76 || 2.76 || 3.84 || 3.91 || 3.84 || 3.84 |
------------------------------------------------------------------------------------------------
Analog / Digital IO results
Pin.no / DigitalWrite / WriteReg / DigitalRead / ReadReg / AnalogRead 8bit / AnalogRead 10bit / AnalogRead 12bit
--------------------------------------------------------------------------------------------------------------------------------
| Pin 0|| Pin 1|| Pin 2|| Pin 3|| Pin 4|| Pin 5|| Pin 6|| Pin 7|| Pin 8|| Pin 9|| Pin10|| Pin11|| Pin12|| Pin13|| Pin14|| Pin15|
--------------------------------------------------------------------------------------------------------------------------------
| 1.41 || 1.36 || 1.36 || 1.28 || 1.41 || 1.36 || 1.36 || 1.28 || 1.41 || 1.36 || 1.36 || 1.28 || 1.29 || 1.36 || 1.25 || 1.16 |
--------------------------------------------------------------------------------------------------------------------------------
| 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 || 0.05 |
--------------------------------------------------------------------------------------------------------------------------------
| 1.13 || 1.08 || 1.08 || 1.04 || 1.13 || 1.08 || 1.08 || 1.04 || 1.13 || 1.08 || 1.08 || 1.04 || 1.13 || 1.08 || 1.08 || 1.04 |
--------------------------------------------------------------------------------------------------------------------------------
| 0.12 || 0.12 || 0.12 || 0.12 || 0.12 || 0.12 || 0.12 || 0.12 || 0.12 || 0.12 || 0.12 || 0.12 || 0.12 || 0.12 || 0.12 || 0.12 |
--------------------------------------------------------------------------------------------------------------------------------
| 3.39 || 3.38 || 3.38 || 3.38 || 3.38 || 3.38 || 3.38 || 3.38 || 3.38 || 3.38 || 3.38 || 3.38 |
------------------------------------------------------------------------------------------------
| 3.47 || 3.47 || 3.47 || 3.47 || 3.47 || 3.47 || 3.47 || 3.47 || 3.47 || 3.47 || 3.47 || 3.47 |
------------------------------------------------------------------------------------------------
| 3.40 || 3.40 || 3.40 || 3.40 || 3.40 || 3.40 || 3.40 || 3.40 || 3.40 || 3.40 || 3.40 || 3.40 |
------------------------------------------------------------------------------------------------

all are 50000 Iterations.

and for WriteReg and ReadReg i used this code:

inline void digitalWriteDirect(int pin, boolean val) {
  if (val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

inline int digitalReadDirect(int pin) {
  return !!(g_APinDescription[pin].pPort -> PIO_PDSR & g_APinDescription[pin].ulPin);
}

Riva:
I had noticed the Mega seemed slower at digital I/O but never bothered to investigate as it was analogue I was interested in. Maybe it's due to core differences in how pins are read/written as pin 9 is PWM on both UNO & MEGA and don't seem to serve as multi function pins (I2C, SPI, UART etc.) that may slow things down. The only other possibility I can think of is interrupt overheads as I don't disable them for testing but analogue read is the same between both UNO & Mega.

The Mega has at least one overly bloated #define for the digitalPinToPCICRbit macro, in the 1.6.7 version. The 6 comparisons of the pin number could be reduced to 2, which yield a result different from zero.

Dunno if that (all those #defines in pins_arduino.h) affects digital I/O timing, though. The mapping of pins to ports and bits is straight forward (array index), no comparisons there.

I do not know if people will see this, but I ran the benchmark on the Arduino 101, using the IDE 1.6.9. I also added the feature to time an analog-write / PWM on pin 9 and I compensated for the time it took to map the values (by timing them as well).

These are my results for the Arduino 101, doing 5000 iterations as well:

Digital Write: 1.5634 Microseconds (.31 nanoseconds per execution)
Digital Read: 1.3131 Microseconds (.26 nanoseconds per execution)
Analog Read: 27.9999 Microseconds (5.59 nanoseconds per execution)
Analog Write (PWM): 2.2391 Microseconds (.44 nanoseconds per execution)
Mapping 0-5000 to 0-255: 1.9063 Microseconds (.38 nanoseconds per execution)

This is the code I used, after modifying it for the mapping and PWM timers. Credit goes to the original Author Riva.

/* Benchmark V2.0 02-June-2015  */

#define targetBoard "Arduino 101"
#define ideVersion "Arduino IDE v1.6.9"
#define analoguePin A0
#define digitalPin 9
#define ledPin 1

#define loopCount 50000   // Max 65535

void setup() {
  Serial.begin(115200);
  while (!Serial) ;
  pinMode(ledPin,OUTPUT);
  digitalWrite(ledPin,LOW);
  
  pinMode(analoguePin,INPUT);
}

void loop() {
  unsigned long startTime;
  unsigned long totalTime;
  unsigned int x;
  int ar;
  int y;
  
  Serial.print(F(targetBoard));
  Serial.print(F(" I/O Speed Tests Over "));
  Serial.print(loopCount, DEC);
  Serial.print(F(" Iterations. Compiled Using "));
  Serial.println(F(ideVersion));
  Serial.flush();
  delay(1000);
  
  // Digital Write
  pinMode(digitalPin,OUTPUT);
  digitalWrite(ledPin,HIGH);
  startTime = micros();
  for (x = 0; x < loopCount; x++){
    digitalWrite(digitalPin,HIGH);
    digitalWrite(digitalPin,LOW);
  }
  totalTime = micros() - startTime;
  digitalWrite(ledPin,LOW);
  Serial.print(F("Digital Pin Write Takes About "));
  //Serial.print(totalTime / 2);
  //Serial.print(F(" Microseconds And Each 'digitalWrite' Took About "));
  Serial.print((float)totalTime / (float)loopCount / 2.0, 4);
  Serial.println(F(" Microseconds."));
  Serial.flush();
  delay(1000);
  
  // Digital Read
  pinMode(digitalPin,INPUT);
  digitalWrite(ledPin,HIGH);
  startTime = micros();
  for (x = 0; x < loopCount; x++){
    ar = digitalRead(digitalPin);
  }
  totalTime = micros() - startTime;
  digitalWrite(ledPin,LOW);
  Serial.print(F("Digital Pin Read  Takes About "));
  Serial.print((float)totalTime / (float)loopCount, 4);
  Serial.println(F(" Microseconds."));
  Serial.flush();
  delay(1000);
  
  // Analogue
  digitalWrite(ledPin,HIGH);
  startTime = micros();
  for (x = 0; x < loopCount; x++){
      ar = analogRead(analoguePin);
  }
  totalTime = micros() - startTime;
  digitalWrite(ledPin,LOW);
  Serial.print(F("Analogue Pin Read Takes About "));
  //Serial.print(totalTime / 2);
  //Serial.print(F(" Microseconds And Each 'digitalWrite' Took About "));
  Serial.print((float)totalTime / (float)loopCount, 4);
  Serial.println(F(" Microseconds."));
  Serial.flush();
  delay(1000);

  //AnalogWrite
  digitalWrite(ledPin, HIGH);
  startTime = micros();
  for (x = 0; x < loopCount; x++){
    analogWrite(9, map(x, 0, loopCount, 0, 255));
  }
  totalTime = micros() - startTime;
  digitalWrite(ledPin, LOW);
  Serial.print(F("PWM Write Takes About "));
  //Serial.print(totalTime / 2);
  //Serial.print(F(" Microseconds And Each 'digitalWrite' Took About "));
  Serial.print((float)totalTime / (float)loopCount, 4);
  Serial.println(F(" Microseconds."));
  Serial.println();
  Serial.flush();
  delay(1000); 

  //mapping
  startTime = micros();
  for (x = 0; x < loopCount; x++)
  {
    y = map(x, 0, loopCount, 0, 255);
  }
  totalTime = micros() - startTime;
  Serial.print(F("Mapping Takes About "));
  //Serial.print(totalTime / 2);
  //Serial.print(F(" Microseconds And Each 'digitalWrite' Took About "));
  Serial.print((float)totalTime / (float)loopCount, 4);
  Serial.println(F(" Microseconds."));
  Serial.println();
  Serial.flush();
  delay(1000);   
  
}

Benchmark_IO.ino (3.1 KB)

101 Benchmark.txt (505 Bytes)

Provided that the system clock of the 101 is 32MHz, your times can not be correct. When one instruction takes at least 30ns, how can anything execute faster than that, by a factor of 100?

I ran the benchmark through 5000 iterations, that is the number on the left, to run through the entire loop. I then proceeded to divide each result by 5000 to get the number on the right. I have not made up any numbers (not implying you are saying that). The numbers above are what I received over serial.