Last active
September 26, 2022 02:35
-
-
Save dfyz/c53848427bc7b0ec3e04b40d50898534 to your computer and use it in GitHub Desktop.
Mach-O vs. ELF export benchmark
This file contains 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 <stdlib.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <time.h> | |
#include <dlfcn.h> | |
#include <err.h> | |
#define NSYMS 1000000 | |
#if __linux__ | |
#define LIB_EXT "so" | |
#elif __APPLE__ | |
#define LIB_EXT "dylib" | |
#else | |
#error "huh?" | |
#endif | |
struct sym { | |
char* good_name; | |
char* bad_name; | |
int res; | |
}; | |
struct sym syms[NSYMS] = { | |
#include "syms.inc" | |
}; | |
int main(int argc, char* argv[]) { | |
if (argc != 2) { | |
err(1, "Usage: %s good|bad", argv[0]); | |
} | |
void* lib = dlopen("./lib." LIB_EXT, RTLD_NOW); | |
if (lib == NULL) { | |
err(1, "dlopen: %s", dlerror()); | |
} | |
if (strcmp(argv[1], "good") == 0) { | |
clock_t good_start = clock(); | |
for (size_t ii = 0; ii < NSYMS; ++ii) { | |
int(*f)() = dlsym(lib, syms[ii].good_name); | |
if (f == NULL) { | |
err(1, "%s: %s", syms[ii].good_name, dlerror()); | |
} | |
int actual_val = f(); | |
if (actual_val != syms[ii].res) { | |
err(1, "mismatch: %d vs. %d", actual_val, syms[ii].res); | |
} | |
} | |
clock_t good_end = clock(); | |
printf("Good syms: %.2fms\n", (good_end - good_start) / (double)CLOCKS_PER_SEC * 1e3); | |
} else if (strcmp(argv[1], "bad") == 0) { | |
clock_t bad_start = clock(); | |
for (size_t ii = 0; ii < NSYMS; ++ii) { | |
int(*f)() = dlsym(lib, syms[ii].bad_name); | |
if (f != NULL) { | |
err(1, "%s was somehow found", syms[ii].bad_name); | |
} | |
} | |
clock_t bad_end = clock(); | |
printf("Bad syms: %.2fms\n", (bad_end - bad_start) / (double)CLOCKS_PER_SEC * 1e3); | |
} else { | |
err(1, "Unknown mode: %s", argv[1]); | |
} | |
return 0; | |
} |
This file contains 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
import string | |
import random | |
def random_snake_case(): | |
return '_'.join( | |
''.join(random.choices( | |
string.ascii_lowercase, | |
k=random.randint(5, 15) | |
)) | |
for ii in range(random.randint(2, 5)) | |
) | |
def random_camel_case(): | |
return ''.join( | |
random.choice(string.ascii_uppercase) + ''.join(random.choices( | |
string.ascii_lowercase, | |
k=random.randint(5, 15), | |
)) | |
for ii in range(random.randint(2, 5)) | |
) | |
if __name__ == '__main__': | |
random.seed(42) | |
N = 1_000_000 | |
func_names = [ | |
(ii, random_camel_case() if ii % 2 == 0 else random_snake_case()) | |
for ii in range(N) | |
] | |
with open('lib.c', 'w') as f: | |
for ii, func_name in func_names: | |
print( | |
f'''int {func_name}() {{ | |
return {ii}; | |
}}''' | |
, file=f) | |
random.shuffle(func_names) | |
with open('syms.inc', 'w') as f: | |
for ii, func_name in func_names: | |
bad_name = func_name[:-1] + chr(ord(func_name[-1]) + 1) | |
print(f'{{.good_name = "{func_name}", .bad_name = "{bad_name}", .res = {ii}}},', file=f) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment