4D v14.3

Conseils d’optimisation

Accueil

 
4D v14.3
Conseils d’optimisation

Conseils d’optimisation  


 

 

Il est difficile, voire impossible, de consigner une fois pour toutes des instructions pour “bien programmer”. Tout au plus pouvons-nous renouveler les recommandations générales vous invitant à bien structurer vos programmes, grâce notamment aux possibilités de programmation générique offertes par 4D.
De fait, il est clair que si vous essayez de compiler une base très bien structurée, vous obtiendrez de bien meilleurs résultats que si votre base est mal structurée. Par exemple, si vous écrivez une méthode projet générique qui gère n méthodes objet, vous obtiendrez de bien meilleurs résultats, en interprété comme en compilé, que si les n méthodes objet comportent n fois les mêmes séquences d’instructions.
La qualité de votre programmation peut donc avoir des effets sur la qualité du code compilé.
Si vous débutez, vous améliorerez progressivement votre code 4D grâce à l’habitude. De la même façon, c’est en utilisant fréquemment le compilateur que vous acquerrez les réflexes qui permettent inconsciemment d’aller droit au but.
En attendant cependant, voici quelques conseils et astuces qui vous permettront de gagner du temps dans des opérations simples et fréquentes.

Certaines astuces que nous vous conseillons peuvent rendre votre code moins lisible par une personne extérieure ou par vous-même ultérieurement. En conséquence, n’hésitez pas à assortir vos méthodes de commentaires détaillés. En effet, si les commentaires peuvent parfois ralentir une base interprétée, ils n’ont strictement aucune influence sur les temps d’exécution d’une base compilée.

Les directives de compilation peuvent vous aider à accélérer considérablement votre code.
Par défaut, le compilateur donne le type le plus large possible à vos variables afin de ne pas vous pénaliser. Si vous ne typez pas par une directive de compilation une variable désignée par l’instruction Var:= 5, le compilateur lui donnera le type Réel, même s’il s’agit de l’affectation d’une valeur entière. Nous allons maintenant voir comment, dans certains cas, déclarer une variable peut vous faire gagner beaucoup de temps.

Réels  

Par défaut, le compilateur donne le type Réel aux variables numériques non typées par directive de compilation et si les Propriétés de la base n’indiquent pas le contraire. Or, les calculs sur un Réel sont plus lents que sur un Entier. Lorsque vous êtes sûr qu’un de vos numériques s’exprimera toujours dans votre base sous forme d’un Entier, il est avantageux de le déclarer par la directive de compilation C_ENTIER LONG.
Une bonne habitude à prendre, par exemple, est de systématiquement déclarer vos compteurs de boucles comme Entier par directive de compilation.

Par ailleurs, certaines fonctions standard de 4D renvoient des Entiers (exemple : Code de caractere, Ent...). Si vous affectez le résultat d’une de ces fonctions à une variable non typée de votre base, le compilateur lui donnera le type Réel et non Entier. Pensez donc à déclarer ces variables par des directives de compilation si vous êtes certain qu’elles ne seront utilisées que dans ces conditions.

Prenons un exemple simple. Une fonction renvoyant une valeur aléatoire comprise entre deux bornes peut s’écrire :

 $0:=Modulo(Hasard;($2-$1+1))+$1

Elle renvoie toujours une valeur entière. Si cette fonction est écrite ainsi, le compilateur donnera à $0 le type Réel et non le type Entier ou Entier long. Il est donc préférable d’écrire cette méthode sous la forme :

 C_ENTIER LONG($0)
 $0:=Modulo(Hasard;($2-$1+1))+$1

Le paramètre rendu par la méthode sera plus petit et il sera donc plus rapide de faire appel à cette méthode.

Prenons un autre exemple simple. Supposons que vous ayez déclaré deux variables en Entier long par l’instruction suivante :

 C_ENTIER LONG($var1;$var2)

et qu’une troisième variable non typée reçoive la somme des deux autres :

 $var3:=$var1+$var2.

Il vous faudra explicitement déclarer $var3 comme Entier long si vous voulez effectivement que $var3 soit de type Entier long, sinon le compilateur la typera par défaut en Réel.

Note : Attention au mode de calcul dans 4D. En mode compilé, ce n’est pas le type de la variable recevant le calcul qui détermine le mode de calcul, mais le type des opérandes. Dans l’exemple ci-dessous, le calcul s’effectue sur des Entiers longs :

 C_REEL($var3)
 C_ENTIER LONG($var1;$var2)
 $var1:=2147483647
 $var2:=1
 $var3:=$var1+$var2

$var3 prendra la valeur –2147483648 en mode compilé comme en interprété. Dans l’exemple suivant :

 C_REEL($var3)
 C_ENTIER LONG($var1)
 $var1:=2147483647
 $var3:=$var1+1

pour des raisons d’optimisation, le compilateur considère la valeur 1 comme une valeur entière. $var3 prendra alors la valeur -2147483648 en mode compilé (car le calcul s’effectue sur des Entiers longs) et 2147483648 en mode interprété (car le calcul s’effectue sur des Réels).

Les boutons sont un cas particulier de Réel qu’il est possible de déclarer en Entier long.

Si vous souhaitez tester la valeur d’un caractère, il est plus rapide de faire la comparaison sur son Code de caractere que sur le caractère lui-même. En effet, la routine standard de comparaison de caractères prend en compte toutes les variations du caractère, comme par exemple les accentuations.

Les traitements sur les tableaux à deux dimensions seront mieux gérés si la deuxième dimension est plus grande que la première.

Par exemple, un tableau déclaré sous la forme :

 TABLEAU ENTIER(LeTableau;5;1000)

sera mieux géré qu’un tableau déclaré sous la forme :

 TABLEAU ENTIER(LeTableau;1000;5)

Champs  

Vous gagnerez du temps lorsque, si vous devez effectuer plusieurs calculs sur un champ, vous rangez la valeur de ce champ dans une variable et que vous effectuez vos calculs sur cette variable, plutôt que de faire directement les calculs sur le champ. Illustrons notre propos par un exemple. Prenons la méthode suivante :

 Au cas ou
    :([Client]Dest="Paris")
       Transport:="Coursier"
    :([Client]Dest="Corse")
       Transport:="Avion"
    :([Client]Dest="Etranger")
       Transport:="Service express"
    Sinon
       Transport:="Poste"
 Fin de cas

La séquence ci-dessus sera plus lente à exécuter que si elle avait été écrite de la façon suivante :

 $Dest:=[Client]Dest
 Au cas ou
    :($Dest="Paris")
       Transport:="Coursier"
    :($Dest="Corse")
       Transport:="Avion"
    :($Dest="Etranger")
       Transport:="Service express"
    Sinon
       Transport:="Poste"
 Fin de cas

De même que pour les champs, il est plus rapide de travailler sur une variable intermédiaire que sur un pointeur dépointé. Vous gagnerez énormément de temps si, lorsque vous devez faire plusieurs calculs sur une variable pointée, vous rangez le pointeur dépointé dans une variable.

Vous disposez par exemple d’un pointeur pointant sur un champ ou sur une variable, MonPtr. Ensuite, vous souhaitez faire une série de tests sur la valeur pointée par MonPtr. Vous pouvez écrire :

 Au cas ou
    :(MonPtr->=1)
       Séquence 1
    :(MonPtr->=2)
       Séquence 2
 
 Fin de cas

Il est plus rapide d’exécuter cette série de tests si elle est écrite ainsi :

 Temp:=MonPtr->
 Au cas ou
    :(Temp=1)
       Séquence 1
    :(Temp=2)
       Séquence 2
 
 Fin de cas

Utiliser des variables locales permet, dans bien des cas, de mieux structurer son code. Ces variables présentent d’autres avantages :

  • Les variables locales prennent moins de place en mémoire lors de l’utilisation d’une base : en effet, elles sont créées lorsqu’on entre dans la méthode où elles sont utilisées et détruites dès qu’on sort de cette méthode.
  • Le code généré est optimisé pour les variables locales, en particulier de type Entier long. Pensez-y pour vos compteurs de boucle.

 
PROPRIÉTÉS 

Produit : 4D
Thème : Compilateur
Nom intl. : Optimization Hints

 
VOIR AUSSI  

Guide du typage
Messages d'erreurs
Précisions de syntaxe
Utilisation des directives de compilation

 
UTILISATION DE L'ARTICLE

4D - Langage ( 4D v14 R2)
4D - Langage ( 4D v14 R3)
4D - Langage ( 4D v14.3)
4D - Langage ( 4D v14 R4)

Hérité de : Conseils d’optimisation ( 4D v11 SQL Release 6)