Last active
December 29, 2022 09:54
-
-
Save jef-sure/208bbd829e8b909cfb10ac8bd743b01d to your computer and use it in GitHub Desktop.
ESP32 Indirect function call performance test
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <stdio.h> | |
#include <stdbool.h> | |
#include <unistd.h> | |
#include <limits.h> | |
#include "esp_timer.h" | |
#include "esp_task_wdt.h" | |
#define TEST_COUNT 10000000 | |
int fn_1(int a) { | |
return a * 8; | |
} | |
int fn_4(int a) { | |
return a * 2; | |
} | |
int fn_8(int a) { | |
return a; | |
} | |
int fn_12(int a) { | |
return (a >> 1) + (a >> 3) + (a >> 5) + (a >> 7) + (a >> 9) + (a >> 11) + (a >> 13) + (a >> 15) + (a >> 17); | |
} | |
int fn_16(int a) { | |
return a >> 1; | |
} | |
int direct_if(int fn) { | |
int i, b = 0; | |
if (fn == 1) { | |
for (i = 0; i < TEST_COUNT; ++i) | |
b = fn_1(b + i); | |
} else if (fn == 4) { | |
for (i = 0; i < TEST_COUNT; ++i) | |
b = fn_4(b + i); | |
} else if (fn == 8) { | |
for (i = 0; i < TEST_COUNT; ++i) | |
b = fn_8(b + i); | |
} else if (fn == 12) { | |
for (i = 0; i < TEST_COUNT; ++i) | |
b = fn_12(b + i); | |
} else if (fn == 16) { | |
for (i = 0; i < TEST_COUNT; ++i) | |
b = fn_16(b + i); | |
} | |
return b; | |
} | |
int direct_switch(int fn) { | |
int i, b = 0; | |
switch (fn) { | |
case 1: | |
for (i = 0; i < TEST_COUNT; ++i) | |
b = fn_1(b + i); | |
break; | |
case 4: | |
for (i = 0; i < TEST_COUNT; ++i) | |
b = fn_4(b + i); | |
break; | |
case 8: | |
for (i = 0; i < TEST_COUNT; ++i) | |
b = fn_8(b + i); | |
break; | |
case 12: | |
for (i = 0; i < TEST_COUNT; ++i) | |
b = fn_12(b + i); | |
break; | |
case 16: | |
for (i = 0; i < TEST_COUNT; ++i) | |
b = fn_16(b + i); | |
} | |
return b; | |
} | |
typedef int (*fn_t)(int); | |
enum { | |
TestedFBits = 5 | |
}; | |
fn_t FPointers[TestedFBits] = { fn_1, fn_4, fn_8, fn_12, fn_16 }; | |
int FIndexes[TestedFBits] = { 1, 4, 8, 12, 16 }; | |
int indirect_version(fn_t fn) { | |
int i, b = 0; | |
for (i = 0; i < TEST_COUNT; ++i) { | |
b = fn(b + i); | |
} | |
return b; | |
} | |
int GlobalVar; | |
void app_main(void) { | |
int64_t start_clock, end_clock; | |
start_clock = esp_timer_get_time(); | |
for (int8_t i = 0; i < TestedFBits; i++) { | |
int bits = FIndexes[i]; | |
GlobalVar += direct_if(bits); | |
} | |
end_clock = esp_timer_get_time(); | |
printf("direct_if took: %lld micros\n", end_clock - start_clock); | |
start_clock = esp_timer_get_time(); | |
for (int8_t i = 0; i < TestedFBits; i++) { | |
int bits = FIndexes[i]; | |
GlobalVar += direct_switch(bits); | |
} | |
end_clock = esp_timer_get_time(); | |
printf("direct_switch took: %lld micros\n", end_clock - start_clock); | |
start_clock = esp_timer_get_time(); | |
for (int8_t i = 0; i < TestedFBits; i++) { | |
GlobalVar += indirect_version(FPointers[i]); | |
} | |
end_clock = esp_timer_get_time(); | |
printf("indirect_version took: %lld micros\n", end_clock - start_clock); | |
while (1) { | |
GlobalVar++; | |
} | |
} | |
__DATA__ | |
gcc 11.2 | |
-O2: | |
direct_if took: 1254457 micros | |
direct_switch took: 1672600 micros | |
indirect_version took: 4390699 micros | |
-Os: | |
direct_if took: 1965483 micros | |
direct_switch took: 2132584 micros | |
indirect_version took: 4599714 micros |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment