Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@jckarter
Last active March 5, 2018 00:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jckarter/e134a24123d4db7cc68cf2890389f644 to your computer and use it in GitHub Desktop.
Save jckarter/e134a24123d4db7cc68cf2890389f644 to your computer and use it in GitHub Desktop.
Lots of global pointers
#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