J'ai oublié d'évaluer les performances dans l'article que j'ai écrit plus tôt, "j'ai essayé de viser le FizzBuzz le plus rapide". Es-tu stupide? Pour cette raison, nous avons évalué les performances du programme manquant.
Le programme FizzBuzz créé la dernière fois
$ time -p ./fizzbuzz >/dev/null
real 0.00
user 0.00
sys 0.00
$
Cela n'est pas utile car le temps d'exécution du programme est trop court pour être mesuré avec la commande time. Avec un peu d'ingéniosité
$ time -p (for i in `seq 1 10000`; do ./fizzbuzz; done) >/dev/null
real 6.76
user 4.55
sys 4.41
Une méthode d'exécution multiple et de division du temps d'exécution par le nombre d'exécutions peut être envisagée, mais cette méthode n'est pas adoptée car la répétition par le shell semble être plus coûteuse que le temps d'exécution du programme. Cette fois, j'ai décidé de créer un programme court qui exécute à plusieurs reprises le même programme et l'utilise.
repeat.c
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdbool.h>
#include <unistd.h>
#include <errno.h>
#include <spawn.h>
#include <sys/wait.h>
int main(int argc, char* argv[])
{
int opt;
int n = 1;
bool f = false;
int fd = -1;
opterr = 0;
while ((opt = getopt(argc, argv, "hfn:")) != -1) {
switch (opt) {
case 'h':
default:
fprintf(stderr, "Usage: repeat [options]... command\n");
exit(EXIT_FAILURE);
break;
case 'f':
f = true;
break;
case 'n':
n = atoi(optarg);
break;
}
}
if (f) {
fd = open("/proc/sys/vm/drop_caches", O_WRONLY);
}
for (int i = 1; i <= n; i++) {
if (f && fd >= 0) {
while (write(fd, "1", 1) == -1 && errno == EINTR) {
;
}
}
pid_t pid;
posix_spawn(&pid, argv[optind], NULL, NULL, &argv[optind], NULL);
int status;
wait(&status);
if (status) {
fprintf(stderr, "pid %d: %d\n", pid, status);
exit(status);
}
}
if (f && fd >= 0) {
close(fd);
}
}
cette
$ gcc -Wall -Wextra -O2 repeat.c -o repeat
Compilez comme
python
$ time -p ./repeat -n 10000 ./fizzbuzz >/dev/null
real 1.84
user 1.44
sys 0.48
$
Utilisé comme. L'option de ligne de commande \ -n value's spécifie le nombre de fois que le programme est exécuté de manière répétée, et le nombre produit par la commande time est divisé par le nombre d'exécutions pour obtenir le temps d'exécution par exécution. Une fois que le programme est lu à partir du disque, son contenu est enregistré dans le cache de page, et il n'ira pas lire le disque pendant une exécution répétée. Puisque nous voulons également évaluer la charge de lecture du programme à partir du disque, nous avons fourni une fonction pour exécuter le programme à partir de l'état où le cache de page est effacé en spécifiant l'option de ligne de commande \
-f '. Le cache de page est effacé en écrivant 1 dans / proc / sys / vm / drop_caches, et les privilèges d'administrateur sont requis, il est donc nécessaire d'utiliser sudo ensemble.
$ sudo time -p ./repeat -n 10000 -f ./fizzbuzz >/dev/null
real 85.90
user 3.26
sys 78.85
$
Comme dans l'exemple précédent, le nombre de sortie est divisé par le nombre de répétitions pour obtenir le temps d'exécution incluant le temps de chargement du programme.
Pas d'effacement du cache (* La valeur numérique est le temps (secondes) exécuté 10 000 fois)
Version du lien dynamique en langage C | Version du lien statique en langage C | Version assembleur | |
---|---|---|---|
real | 4.55 | 2.99 | 1.82 |
user | 3.65 | 2.37 | 1.43 |
sys | 0.91 | 0.69 | 0.47 |
Il y a une compensation de trésorerie (* comme ci-dessus)
Version du lien dynamique en langage C | Version du lien statique en langage C | Version assembleur | |
---|---|---|---|
real | 121.74 | 142.39 | 85.90 |
user | 8.15 | 9.46 | 3.26 |
sys | 93.45 | 95.96 | 78.85 |
Taille du fichier d'exécution (* l'unité est en octets)
Version du lien dynamique en langage C | Version du lien statique en langage C | Version assembleur |
---|---|---|
6112 | 714736 | 808 |
La fin.