Time hello, world
The classic first program in various languages plus a wrapper to benchmark them. This is a nice way to measure startup overhead of language runtimes.
This commit is contained in:
commit
f4ffdda200
|
@ -0,0 +1,2 @@
|
||||||
|
#!/usr/bin/awk -f
|
||||||
|
BEGIN { print "Hello, world!" }
|
|
@ -0,0 +1,2 @@
|
||||||
|
#!/bin/bash
|
||||||
|
echo "Hello, world!"
|
|
@ -0,0 +1,3 @@
|
||||||
|
all: hello
|
||||||
|
clean:
|
||||||
|
rm hello
|
|
@ -0,0 +1,6 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
printf("Hello, world!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
#!/bin/dash
|
||||||
|
echo "Hello, world!"
|
|
@ -0,0 +1,26 @@
|
||||||
|
<project name="hello" default="compile" basedir=".">
|
||||||
|
<description>
|
||||||
|
Sieve of Eratosthenes in Java
|
||||||
|
</description>
|
||||||
|
<property name="src" location="src"/>
|
||||||
|
<property name="classes" location="classes"/>
|
||||||
|
|
||||||
|
<target name="clean">
|
||||||
|
<delete dir="classes"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="init">
|
||||||
|
<tstamp/>
|
||||||
|
<mkdir dir="classes"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="compile" depends="init">
|
||||||
|
<javac srcdir="src" destdir="classes" includeantruntime="false" />
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="jar" depends="compile">
|
||||||
|
<jar destfile="hello.jar" basedir="classes"
|
||||||
|
manifest="manifest.mf" />
|
||||||
|
</target>
|
||||||
|
|
||||||
|
</project>
|
Binary file not shown.
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -x
|
||||||
|
java -jar ${0%/*}/hello.jar
|
|
@ -0,0 +1 @@
|
||||||
|
Main-Class: at.hjp.hello.Main
|
|
@ -0,0 +1,7 @@
|
||||||
|
package at.hjp.hello;
|
||||||
|
|
||||||
|
class Main {
|
||||||
|
public static void main(String[] argv) {
|
||||||
|
System.out.println("Hello, world!");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
CFLAGS = -g -Wall -std=gnu11
|
||||||
|
LDFLAGS = -lrt
|
||||||
|
|
||||||
|
timethem:
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm timethem
|
|
@ -0,0 +1,6 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
use warnings;
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
print "Hello, world!\n";
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
use Modern::Perl;
|
||||||
|
|
||||||
|
say "Hello, world!";
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
print "Hello, world!\n";
|
|
@ -0,0 +1,2 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
print("Hello, world!")
|
|
@ -0,0 +1,2 @@
|
||||||
|
#!/bin/zsh -f
|
||||||
|
echo "Hello, world!"
|
|
@ -0,0 +1,93 @@
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define N 5
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double time;
|
||||||
|
size_t nread;
|
||||||
|
} resultT;
|
||||||
|
|
||||||
|
int cmptime(const void *a, const void *b) {
|
||||||
|
const resultT *aa = a, *bb = b;
|
||||||
|
if (aa->time < bb->time) {
|
||||||
|
return -1;
|
||||||
|
} else if (aa->time > bb->time) {
|
||||||
|
return +1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
resultT median (resultT *v, int n) {
|
||||||
|
// n is small, keep it simple
|
||||||
|
qsort(v, n, sizeof(*v), cmptime);
|
||||||
|
return v[n / 2];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
resultT **results = calloc(sizeof(*results), argc);
|
||||||
|
assert(results);
|
||||||
|
for (int i = 1; i < argc; i++) {
|
||||||
|
results[i] = calloc(sizeof(**results), N);
|
||||||
|
assert(results[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < N; j++) {
|
||||||
|
for (int i = 1; i < argc; i++) {
|
||||||
|
struct timespec t0, t1;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &t0);
|
||||||
|
size_t nread = 0;
|
||||||
|
|
||||||
|
int out[2];
|
||||||
|
if (pipe(out) == -1) {
|
||||||
|
printf("%s: cannot create pipe: %s\n", argv[0], strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t pid = fork();
|
||||||
|
switch(pid) {
|
||||||
|
case -1:
|
||||||
|
fprintf(stderr, "%s: cannot fork: %s\n", argv[0], strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
case 0:
|
||||||
|
dup2(out[1], 1);
|
||||||
|
// close(out[0]);
|
||||||
|
// close(out[1]);
|
||||||
|
execl(argv[i], argv[i], (char *)NULL);
|
||||||
|
fprintf(stderr, "%s: cannot exec %s: %s\n", argv[0], argv[i], strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
default: {
|
||||||
|
close(out[1]);
|
||||||
|
ssize_t n;
|
||||||
|
char buf[16];
|
||||||
|
while ((n = read(out[0], buf, sizeof(buf))) > 0) {
|
||||||
|
nread += n;
|
||||||
|
}
|
||||||
|
int status;
|
||||||
|
while (waitpid(pid, &status, 0) != pid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &t1);
|
||||||
|
results[i][j].time = (t1.tv_sec - t0.tv_sec) * 1E9 + (t1.tv_nsec - t0.tv_nsec);
|
||||||
|
results[i][j].nread = nread;
|
||||||
|
fprintf(stderr, "%s: %s completed in %f ns\n", argv[0], argv[i], results[i][j].time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 1; i < argc; i++) {
|
||||||
|
resultT m = median(results[i], N);
|
||||||
|
printf("%-20s %8.3f ms %2d bytes\n", argv[i], m.time / 1E6, m.nread);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue