mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 11:37:35 +00:00
142 lines
4.1 KiB
C
142 lines
4.1 KiB
C
#if 0
|
|
/*─────────────────────────────────────────────────────────────────╗
|
|
│ To the extent possible under law, Justine Tunney has waived │
|
|
│ all copyright and related or neighboring rights to this file, │
|
|
│ as it is written in the following disclaimers: │
|
|
│ • http://unlicense.org/ │
|
|
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
|
╚─────────────────────────────────────────────────────────────────*/
|
|
#endif
|
|
#include <spawn.h>
|
|
#include <stdalign.h>
|
|
#include <stdatomic.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/mman.h>
|
|
#include <time.h>
|
|
|
|
#define ITERATIONS 10
|
|
|
|
alignas(128) int a;
|
|
alignas(128) int b;
|
|
alignas(128) atomic_int lock;
|
|
|
|
static struct timespec SubtractTime(struct timespec a, struct timespec b) {
|
|
a.tv_sec -= b.tv_sec;
|
|
if (a.tv_nsec < b.tv_nsec) {
|
|
a.tv_nsec += 1000000000;
|
|
a.tv_sec--;
|
|
}
|
|
a.tv_nsec -= b.tv_nsec;
|
|
return a;
|
|
}
|
|
|
|
static time_t ToNanoseconds(struct timespec ts) {
|
|
return ts.tv_sec * 1000000000 + ts.tv_nsec;
|
|
}
|
|
|
|
static char *Ithoa(char p[27], unsigned long x) {
|
|
char m[26];
|
|
unsigned i;
|
|
i = 0;
|
|
do {
|
|
m[i++] = x % 10 + '0';
|
|
x = x / 10;
|
|
} while (x);
|
|
for (;;) {
|
|
*p++ = m[--i];
|
|
if (!i)
|
|
break;
|
|
if (!(i % 3))
|
|
*p++ = ',';
|
|
}
|
|
*p = '\0';
|
|
return p;
|
|
}
|
|
|
|
#define BENCH(name, x) \
|
|
{ \
|
|
int i; \
|
|
char ibuf[27]; \
|
|
struct timespec t1, t2; \
|
|
clock_gettime(CLOCK_REALTIME, &t1); \
|
|
for (i = 0; i < ITERATIONS; ++i) { \
|
|
x; \
|
|
} \
|
|
clock_gettime(CLOCK_REALTIME, &t2); \
|
|
Ithoa(ibuf, ToNanoseconds(SubtractTime(t2, t1)) / ITERATIONS); \
|
|
printf("%-50s %16s ns\n", name, ibuf); \
|
|
}
|
|
|
|
void PosixSpawnWait(const char *prog) {
|
|
int ws, err, pid;
|
|
char *args[] = {(char *)prog, 0};
|
|
char *envs[] = {0};
|
|
if ((err = posix_spawn(&pid, prog, NULL, NULL, args, envs))) {
|
|
perror(prog);
|
|
exit(1);
|
|
}
|
|
if (waitpid(pid, &ws, 0) == -1) {
|
|
perror("waitpid");
|
|
exit(1);
|
|
}
|
|
if (!(WIFEXITED(ws) && WEXITSTATUS(ws) == 42)) {
|
|
puts("bad exit status");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
void ForkExecWait(const char *prog) {
|
|
int ws;
|
|
if (!fork()) {
|
|
execve(prog, (char *[]){(char *)prog, 0}, (char *[]){0});
|
|
_Exit(127);
|
|
}
|
|
if (wait(&ws) == -1) {
|
|
perror("wait");
|
|
exit(1);
|
|
}
|
|
if (!(WIFEXITED(ws) && WEXITSTATUS(ws) == 42)) {
|
|
puts("bad exit status");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
char *FillMemory(char *p, long n) {
|
|
return memset(p, -1, n);
|
|
}
|
|
char *(*pFillMemory)(char *, long) = FillMemory;
|
|
|
|
int main(int argc, char *argv[]) {
|
|
long n;
|
|
void *p;
|
|
const char *prog;
|
|
|
|
// if you need the tiny64 program for windows:
|
|
//
|
|
// make -j o//tool/hello/life-pe.ape
|
|
// scp o//tool/hello/life-pe.ape windows:tiny64
|
|
//
|
|
if (argc <= 1) {
|
|
prog = "tiny64";
|
|
} else {
|
|
prog = argv[1];
|
|
}
|
|
|
|
BENCH("fork() + exec(tiny)", ForkExecWait(prog));
|
|
BENCH("posix_spawn(tiny)", PosixSpawnWait(prog));
|
|
|
|
n = 128L * 1024 * 1024;
|
|
p = pFillMemory(
|
|
mmap(0, n, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0), n);
|
|
BENCH("mmap(128mb, MAP_SHARED) + fork() + exec(tiny)", ForkExecWait(prog));
|
|
BENCH("mmap(128mb, MAP_SHARED) + posix_spawn(tiny)", PosixSpawnWait(prog));
|
|
munmap(p, n);
|
|
|
|
n = 128L * 1024 * 1024;
|
|
p = pFillMemory(malloc(n), n);
|
|
BENCH("malloc(128mb) + fork() + exec(tiny)", ForkExecWait(prog));
|
|
BENCH("malloc(128mb) + posix_spawn(tiny)", PosixSpawnWait(prog));
|
|
free(p);
|
|
}
|