C:\8BIT> dir /w

Rétro-informatique, électronique et émulation — journal d’atelier

, ,

Statique ou instance ? Ce que le banc d’essai a tranché

En reprenant iXtal26 avec PCem comme référence d’architecture, une même question revient devant chaque composant : faut-il passer l’objet en paramètre, comme le fait PCem en C avec son void *p, ou le placer à une adresse statique que le JIT connaît d’avance ? Plutôt que de trancher à l’intuition, je l’ai mesuré.

La question

Dans PCem, chaque fonction du chemin vidéo reçoit un pointeur opaque qu’elle convertit en svga_t. Transposé en C#, cela donne la variante A : l’instance voyage avec chaque appel. La variante B range l’objet dans un champ statique ; le JIT connaît alors son adresse à la compilation et économise, en théorie, une indirection à chaque accès. Sur un chemin exécuté des millions de fois par seconde, l’écart pouvait compter. Il restait à savoir s’il existait.

// file: Schéma des deux variantes (simplifié)
// Variante A : l'instance voyage avec l'appel, comme le void *p de PCem
static void SvgaWrite(uint addr, byte val, object p)
{
    var svga = (Svga)p;
    // …
}

// Variante B : l'objet vit à une adresse statique connue du JIT
static void SvgaWrite(uint addr, byte val)
{
    var svga = Video.Svga;
    // …
}

Le protocole

La machine émulée est un 286 avec une Trident 8900D sous Windows 3.11. Les deux variantes portent sur les dix fonctions du chemin vidéo : svga_write, svga_read, leurs déclinaisons 16 et 32 bits (writew, writel, readw, readl), svga_poll, svga_in, svga_out et l’affichage d’état. Chaque passe part d’une copie neuve du disque, sur quatre cœurs rapides, et chronomètre le démarrage DOS, le lancement de Windows puis deux minutes émulées. Cinq passes par variante, en alternance, pour que la dérive thermique ou le cache disque ne favorisent pas l’une des deux.

VarianteMinimumMédiane
A — instance en paramètre10,40 s10,43 s
B — adresse statique10,38 s10,46 s

L’écart reste dans le bruit de mesure, à ±0,5 %. B gagne sur le minimum et perd sur la médiane : aucune des deux ne domine.

Ce que le résultat tranche

Puisque la vitesse ne départage pas les variantes, le choix revient à ce qui reste : la lisibilité du code et la fidélité à PCem, qui sert de carte pour la reprise. La règle vaut au-delà de la SVGA. Le contrôleur d’interruptions en est le premier bénéficiaire : Intel8259A reste une classe instanciable, puisque le PC en compte deux, le maître et l’esclave, et un conteneur statique les expose au reste de l’émulateur.

// file: Ics.cs (structure)
internal sealed class Intel8259A
{
    // Mask, InService, Pending, Raise(), Reset()…
}

internal static class Ics
{
    public static readonly Intel8259A MasterPic = new();
    public static readonly Intel8259A SlavePic = new();
}

Chaque mot-clé a sa raison. sealed d’abord : un 8259A est figé par sa fiche technique, il n’y a rien à spécialiser, et le JIT peut résoudre les appels sans table virtuelle. C’est d’ailleurs ce que recommande l’analyseur CA1852 pour toute classe interne qui n’est dérivée nulle part. static ensuite, sur le seul conteneur : Ics ne s’instancie pas et ne fait que ranger les deux puces. readonly enfin, avec sa limite : il protège la référence, pas l’objet. Ics.MasterPic ne peut pas être remplacé, mais son masque et ses demandes en cours changent à chaque interruption, et c’est précisément ce qu’on attend d’un contrôleur d’interruptions. L’appel s’écrit alors simplement : Ics.MasterPic.Raise(0).

Note d’atelier. Trois réserves accompagnent ces mesures. Le profilage fin était bloqué par le réglage système perf_event_paranoid, qui demande les droits administrateur. Les deux exécutions divergent après environ 24 secondes émulées, soit une quarantaine de millions d’instructions, très probablement parce que l’horloge temps réel lit l’heure de l’hôte. Enfin, l’option --boot passe le clavier en AZERTY : il faut taper ZIN pour lancer WIN.

La deuxième réserve désigne la suite. Tant que l’horloge temps réel suit celle de l’hôte, deux exécutions ne sont jamais identiques, et toute comparaison fine reste approximative. Rendre cette horloge déterministe est la condition des prochains bancs d’essai.

◂ Précédent

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *