-
-
Save jckarter/e134a24123d4db7cc68cf2890389f644 to your computer and use it in GitHub Desktop.
Lots of global pointers
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 <mach/mach_time.h> | |
#include <mach-o/dyld.h> | |
#include <inttypes.h> | |
#include <signal.h> | |
#include <spawn.h> | |
#include <stdint.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <sys/param.h> | |
#include <sys/wait.h> | |
struct class { | |
const char *name; | |
void (*method1)(void); | |
void (*method2)(void); | |
void (*method3)(void); | |
void (*method4)(void); | |
void (*method5)(void); | |
void (*method6)(void); | |
void (*method7)(void); | |
}; | |
void fake_method() {} | |
#if !defined(VARIATION) || VARIATION < 0 || VARIATION > 2 | |
#error "Please pass -DVARIATION=[012] to the compiler. " \ | |
"0 = no globals; 1 = 256K non-pointer globals; 2 = 256K pointer globals" | |
#endif | |
#if VARIATION >= 1 | |
// Create 4096 class records | |
#define LOTS(x) \ | |
x(__COUNTER__) x(__COUNTER__) x(__COUNTER__) x(__COUNTER__) \ | |
x(__COUNTER__) x(__COUNTER__) x(__COUNTER__) x(__COUNTER__) | |
#define LOTS_AND_LOTS(x) \ | |
LOTS(x) LOTS(x) LOTS(x) LOTS(x) \ | |
LOTS(x) LOTS(x) LOTS(x) LOTS(x) | |
#define LOTS_AND_LOTS_AND_LOTS(x) \ | |
LOTS_AND_LOTS(x) LOTS_AND_LOTS(x) LOTS_AND_LOTS(x) LOTS_AND_LOTS(x) \ | |
LOTS_AND_LOTS(x) LOTS_AND_LOTS(x) LOTS_AND_LOTS(x) LOTS_AND_LOTS(x) | |
#define LOTS_AND_LOTS_AND_LOTS_AND_LOTS(x) \ | |
LOTS_AND_LOTS_AND_LOTS(x) LOTS_AND_LOTS_AND_LOTS(x) LOTS_AND_LOTS_AND_LOTS(x) LOTS_AND_LOTS_AND_LOTS(x) \ | |
LOTS_AND_LOTS_AND_LOTS(x) LOTS_AND_LOTS_AND_LOTS(x) LOTS_AND_LOTS_AND_LOTS(x) LOTS_AND_LOTS_AND_LOTS(x) | |
#if VARIATION == 1 | |
#define CLASS_(nam) \ | |
const struct class nam = { \ | |
.name = (void*)1, \ | |
.method1 = (void*)2, \ | |
.method2 = (void*)3, \ | |
.method3 = (void*)4, \ | |
.method4 = (void*)5, \ | |
.method5 = (void*)6, \ | |
.method6 = (void*)7, \ | |
.method7 = (void*)8 \ | |
}; | |
#else | |
#define CLASS_(nam) \ | |
const struct class nam = { \ | |
.name = #nam, \ | |
.method1 = fake_method, \ | |
.method2 = fake_method, \ | |
.method3 = fake_method, \ | |
.method4 = fake_method, \ | |
.method5 = fake_method, \ | |
.method6 = fake_method, \ | |
.method7 = fake_method \ | |
}; | |
#endif | |
#define CLASS(nam) CLASS_(nam) | |
#define CAT_(a, b) a ## b | |
#define CAT(a, b) CAT_(a, b) | |
#define OF_CLASSES(n) CLASS(CAT(class, n)) | |
LOTS_AND_LOTS_AND_LOTS_AND_LOTS(OF_CLASSES) | |
#endif | |
int main(int argc, char *argv[], char *envp[]) { | |
if (argc < 3) { | |
// Respawn ourselves to measure the pre-main startup time. | |
char time_buffer[22]; | |
char path_buffer[MAXPATHLEN+1]; | |
uint32_t path_buffer_size = MAXPATHLEN+1; | |
if (_NSGetExecutablePath(path_buffer, &path_buffer_size)) { | |
perror(argv[0]); | |
return 1; | |
} | |
char *sub_argv[] = { | |
argv[0], | |
argv[1] ? argv[1] : "-", | |
time_buffer, | |
0 | |
}; | |
// Measure the time right before posix_spawning the child process. | |
uint64_t time = mach_absolute_time(); | |
sprintf(time_buffer, "%" PRIu64, time); | |
pid_t pid; | |
if (posix_spawn(&pid, path_buffer, 0, 0, sub_argv, envp)) { | |
perror(argv[0]); | |
return 1; | |
} | |
int stat; | |
waitpid(pid, &stat, WUNTRACED); | |
// Stop so we can inspect the process memory usage. | |
if (argv[1] && strcmp(argv[1], "-stop") == 0) { | |
pid_t pid = getpid(); | |
printf("pid %u\n", (unsigned)pid); | |
raise(SIGSTOP); | |
} | |
return 0; | |
} else { | |
// We should have been passed the pre-spawn time in argv[2]. | |
// Measure the time immediately after entering main. | |
uint64_t time = mach_absolute_time(); | |
unsigned long long start_time = strtoull(argv[2], 0, 10); | |
uint64_t elapsed = time - start_time; | |
// Convert mach time units to nanoseconds. | |
mach_timebase_info_data_t timebase; | |
mach_timebase_info(&timebase); | |
typedef unsigned __int128 uint128_t; | |
uint64_t nanoseconds = (uint128_t)elapsed * (uint128_t)timebase.numer / timebase.denom; | |
printf("%" PRIu64 " nanoseconds from spawn to main() entry\n", nanoseconds); | |
return 0; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment