ifuncd-up icon indicating copy to clipboard operation
ifuncd-up copied to clipboard

Performance comparison: Function pointers in memory-protected global struct

Open robertdfrench opened this issue 1 year ago • 3 comments

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);
}

robertdfrench avatar Aug 31 '24 00:08 robertdfrench

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.

robertdfrench avatar Aug 31 '24 04:08 robertdfrench