Ce billet entame une description sommaire du fonctionnement interne de FoxPro



Il est inspiré du travail de Christof Wollenhaupt, Foxpert

How FoxPro works internally FoxPro Inside Out

A l’origine, xBase était un outil de manipulation des données, pas un langage de programmation. Les utilisateurs n’en étaient pas des développeurs, mais des experts dans une variété considérable de domaines qui utilisaient pour gérer leurs données FoxBase, dBase, etc. FoxPro devint un environnement de développement qui évolua en 1995 de la programmation procédurale vers les concepts orientés objet. Contrairement à la plupart des langages, Visual FoxPro contient toujours ses racines. Du code écrit dans les années 80 peut tourner aujourd'hui en VFP 9 prés de 20 ans après avoir été écrit. Visual FoxPro offre une compatibilité ascendante presque totale. L’orientation Objet réside au dessus des couches de FoxPro, pas le contraire, ce qui explique bien des comportements de VFP.

L’index de table des noms (Name Table Index - NTI)

Visual FoxPro assigne un nom (name) à différents items: variables, noms de tableaux (array), procédures, fonctions, alias de tables, noms de champs et d’objets. Chacun de ces éléments reçoit un label et une plage de référence. La visibilité (l’étendue) d’une variable dépend de son type, alors que l’étendue d’un alias est la session de données. Un nom de champ doit être unique dans une table et une procédure est visible dans un fichier programme.
A chaque création de variable, ouverture de table, etc, Visual FoxPro crée une nouvelle entrée dans une liste interne, la Table des Noms (Name Table). La position interne à cette liste est l’index de la table des noms Name Table Index – (NTI). Chaque nom dans cette liste reçoit un numéro unique entre 1 et 65,000, (c’est une valeur 16-bit). C’est la raison de la limitation du nombre de variables à 65,000. Réduite du nombre de zones de travail allouées et d’instances d’objets (depuis Visual FoxPro 6.0).
Cette liste est purgée par un processus appellé Garbage Collection, terme se référant à la suppression des entrées invalides de la liste, la libération des tampons périmés, le compactage de la mémoire utilisée, la vérification de l’accès aux fichiers temporaires, etc.
VFP l’exécute dans l’idle loop. VFP entre dans cette boucle dès qu’une condition d’attente intervient: READ, READ EVENTS, INKEY(), ou WAIT WINDOW, même si une option nowait est indiquée.
WAIT WINDOW "" NOWAIT est un “truc” utilisé pour vider la mémoire.

Apparu dans la documentations de VFP 7.0 SYS(1104) permet, depuis au moins Foxpro 2.6, de déclencher une Garbage Collection, ce n’est pas identique à un état d’attente, car celui ci en fait un peu plus, comme l’affichage des messages systèmes. En exécution d’un programme, VFP n’éxécute pas idle loop. Jusque VFP 5.0 cela avait l’inconvénient d’un encombrement de la table des noms, avec des conséquences sur la performance, mais aussi la stabilité. A chaque nouvelle entrée dans la table, VFP vérifie la possibilité de conflits potentiels. Par exemple, une variable PUBLIC ne peut être créée si une variable LOCAL de même nom existe, un ALIAS identique dans la même session de données etc. Ce processus de vérification entraine une dégradation exponentielle des performances quand la table des noms grandit (de quelques naosecondes à la minute du 1er au 60000ème objet).

Les applications qui n’atteignent jamais un état d’attente comme des routines d’import ou des fournisseurs de services deviennent de plus en plus lentes pendant leur exécution. D’autres fonctions (Comme le recalcul d’une vue, REQUERY() ) requièrent une entrée nouvelle dans la table des noms. Le ralentissement n’est pas le seul problème, lorsqu’une application approche de la limite, elle devient instable, avec un peu de chance, VFP emet le message « Too many names used » (Error 1201) mais, le plus souvent elle “plante”.
VFP 6.0 a beaucoup amélioré ce comportement en lançant un garbage collection automatique lorsque la table des noms approche 95 % de la limite.

VFP 7.0 apporta une amélioration majeure. Toutes les versions précédentes comptaient les objets.
Quand 2 labels étaient créés:

LOCAL loLabel1, loLabel2
loLabel1 = CreateObject("Label")
loLabel2 = CreateObject("Label")

Visual FoxPro ajustait la propriété “name”. Le premier label étant appelé “Label1”, le second “Label2” pour cela, VFP enregistrait chaque objet dans la table des noms.
En conséquence, chaque création d’objet durait plus longtemps que la précédente. L’utilisation de SYS(2015) dans l’évènement init pouvait bypasser cela jusqu’à un certain point. Quoiqu’il en soit, ce comportement limitait le nombre d’objets qui pouvaient être instanciés à 65000.
De VFP 3.0 à VFP 6.0 il n’était pas possibe de créer plus de 65000 objets, y compris ceux contenus dans les formulaires. Cette limite atteinte, le générateur de Formulaires ne pouvait même pas être ouvert.

A partir de VFP 7.0 un nom unique n’est plus requis pour les objets, dont le nom n'est plus enregistré dans la table des noms. De ce fait la limite de 65000 objets peut être dépassée, et la rapidité en est accrue. L’inconvénient est que les noms d’objets ne sont plus uniques, un petit prix à payer.