ifuncd-up
ifuncd-up copied to clipboard
Performance comparison: Function pointers in memory-protected global struct
from @nekopsykose
#include <err.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdio.h>
struct myfuncs {
unsigned (*multiply)(unsigned, unsigned);
};
static struct myfuncs *page;
unsigned multiply_base(unsigned x, unsigned y) {
return x * y;
}
unsigned multiply_sse42(unsigned x, unsigned y) {
return x + y; /* lol */
}
void initfuncs(void) {
int pagesize = getpagesize();
page = mmap(NULL, pagesize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, 0, 0);
if (page == MAP_FAILED)
err(123, "mmap");
/* magical runtime check */
if (0) {
page->multiply = multiply_sse42;
} else {
page->multiply = multiply_base;
}
if(mprotect(page, pagesize, PROT_READ))
err(123, "mprotect");
/* segfaults */
// page->multiply = multiply_sse42;
}
int main(void) {
initfuncs();
unsigned x = page->multiply(4, 4);
printf("%u\n", x);
}
| TEST | LOW | HIGH | AVG |
|---|---|---|---|
| fixed | 2.00 | 2.21 | 2.092 |
| pointer | 3.90 | 4.59 | 4.341 |
| struct | 3.61 | 3.88 | 3.76 |
| ifunc | 5.29 | 5.70 | 5.514 |
| upfront | 7.75 | 8.04 | 7.875 |
| always | 12.88 | 13.70 | 13.448 |
So the "Struct of pointers in its own page" approach seems slightly faster than the "global static pointer not necessarily in its own page" approach, thought I'm not sure why that should be the case.