Mini tuto sur l'optimisation

Contenu du snippet

juste quelques lignes à lire, j'espère que ça vous aidera ;)

Pour ceux que ça intéressent: http://www.xdb.exagon.org/optimisation.htm
la version html de ce tuto (:

Source / Exemple :


-  Introduction

la confection de ce petit tutorial m'est venu à l'esprit pour répondre aux demandes usuelles des utilisateurs sur les différents forums de scripting et sur IRC.
La plupart du temps ce sont les mêmes questions qui reviennent, de ce fait j'ai commencé à regrouper plein de petites astuces et d'optimisations de code
qui vont vous permettre d'améliorer soit la rapidité soit la clarté de votre code, bonne lecture !

- Généralités

? Aliases:

- Couleurs/gras/souligner:

Au lieu de vous embarrasser avec des ctrl+k/ctrl+b/ctrl+u qui vous affichent des carrés dont vous ne savez au final plus à quoi ils correspondent, privilégiez la création
de petites aliases de la forme:

alias c return $+($+($chr(3),$2),$1,$chr(3)))
alias u return $+($chr(31),$1,$chr(31))
alias b return $+($chr(2),$1,$chr(2))

ex:

//echo -a $b(<texte>) $c(<texte>,4) ... => vous obtiendrez <texte> <texte>

vous pouvez aussi les combiner pour obtenir quelque chose comme:

//echo -a $b($c(<texte>,12)) => vous obtiendrez <texte>

cela vous permettra d'avoir un code plus clair pour vous relire par la suite, et
vous n'aurez plus de problèmes lorsque vous ferez un c/c de votre code.

par la suite si vous en avez besoin vous pourrez retoucher vos aliases pour
les complexifier:

alias b { var %s , %x = $regsub($1,$iif(!$prop,^(.+)$,$iif(- == $left($prop,1),(.{1 $+ $chr(44) $+ $right($prop,-1) $+ })$ ,^ $+ (.{1 $+ $chr(44) $+ $prop $+ }))),$+($chr(2),\1,$chr(2)),%s) | return %s }

ce qui fera que si vous tapez:

//echo -a $b(exemple).1 => seulement la première lettre sera en gras: exemple
//echo -a $b(exemple2).5 => les 5 premières lettres seront en gras: exemple2
//echo -a $b(exemple3).-3 => les 3 dernières lettres seront en gras: exemple3
etc...

- Design:

Souvent lorsque l'on voit les gens faire leurs events, à chaque ligne qui est en echo on retrouve le même design, de ce fait de la même façon que tout à l'heure, faîtes des petites aliases !

alias cro return $+($chr(91),$1-,$chr(93))

ex:

//echo -a $cro(<texte>) => vous obtiendrez [<texte>]

Et de la même façon si vous le souhaitez, par la suite vous pourrez l'améliorer, par exemple:

alias cro return $iif($1 isnum 0-15,$iif($prop == b,$+($c($chr(91),$1),$c($b($3-),$2),$c($chr(93),$1)),$+($c($chr(91),$1),$c($3-,$2),$c($chr(93),$1))),invalid parameters: $!x.cro(N(1-15),N(?),texte))

//echo -a $cro(1,4,texte).b => retournera [texte] avec les crochets de la couleur n°1, le texte de la couleur n°4 et en gras.

- Fichiers:

Lorsque vous vous faîtes des aliases qui vont chercher des fichiers, dans un premier temps pensez à mettre le 'path' ou le chemin de votre fichier entre guillemets, cela fera en sorte que si le path contient des espaces, le fichier sera quand même accessible avec mIRC.

ex:

alias -l t.mdx { dll $+(",$scriptdir,mdx.dll,") $1- }

Maintenant, nous allons voir qu'il est plus judicieux de combiner des aliases que d'en faire plein partout.

ex:

alias -l mdx { return $+(",$scriptdir,mdx.dll,") }
alias -l views { return $+($scriptdir,Views.mdx) }

Ces deux aliases sont correctes, mais si l'on veut utiliser une commande qui requiert views.mdx on devra faire:
//dll $mdx SetControlMDX Dialog ID ListView Style > $views

Pour contourner cela, nous pouvons créer des aliases de cette forme:

alias -l mdx { dll $+(",$scriptdir,mdx.dll,") $1- }
alias -l views { mdx $1- > $+($scriptdir,views.mdx) }

Cela nous permettra d'utiliser seulement l'aliase views et de raccourcir la commande:
//views SetControlMDX Dialog ID ListView Style

? If/else:

Lorsque vous avez juste un 'if' et un 'else', privilégiez l'utilisation de l'identifieur $iif(), même si on perd un peu de la clarté du code...

ex:

//if $nick == $me { echo -a $true } | else { echo -a $false }

on peut remplacer ceci par:

//echo -a $iif($nick == $me,$true,$false)

Et si vous préférez garder les if, vous pourrez souvent regrouper un peu les conditions entre elles:

//if $me == tofu { if $nick == pseudo1 || $nick == pseudo2 ...... { } }

vous pouvez faire:

//if $me == tofu && $nick isin pseudo1;pseudo2;pseudo3 { }

Remarque: l'identifieur $iif() est plus lent que l'utilisation de 'if/else' donc lors de l'utilisation de boucles qui risquent d'être assez grosses,
privilégiez l'utilisation de 'if/else'.

Au niveau de la syntaxe d'un if/else aussi, une différence de rapidité peut survenir selon celle que l'on utilise, effectivement en testant sur une simple boucle:

alias t.t { var %ù = $ticks, %ù! = 1 | while %ù! <= 300 { if (%var) { echo -a $true } | inc %ù! } | echo -a Exécution en: $calc($ticks - %ù) }

l'on peut constater:

//if (%var) cmd => 93ms
//if %var { cmd } => 94ms
//if (%var) { cmd } => 110 ms

? $+()/$+:

Lorsque vous voulez 'coller' certaines choses entre elles, au lieu d'utiliser $+ entre chaque chaîne, utilisez plutôt $+() en séparant chaque chaîne avec des virgules.

ex:

alias b return $chr(2) $+ $1 $+ $chr(2)

alias b return $+($chr(2),$1,$chr(2))

Avec ceci vous gagnerez de la place, de la clarté, et surtout si vous voulez ajouter quelque chose, vous n'avez qu'à rajouter une virgule entre les parenthèses et rajouter une chaîne.

? Write:

De la même façon que pour les 'on text', souvent on voit plein de /write à la chaîne. Lorsque vous voulez sauter de ligne, pensez à $crlf !

faire: write fichier.txt <ligne1> | write fichier.txt <ligne2> etc....

revient à faire: write fichier.txt $+(<ligne1>,$crlf,<ligne2>,$crlf,<ligne3>,.....)

Pour optimiser le temps de lecture d'un fichier, vous pouvez privilégier l'utilisation du file handling au lieu d'utiliser $read().

ex:

alias r.t { var %ù = 1 , %ù! = $lines(mirc.ini) | while %ù <= %ù! { echo -a $read(mirc.ini,n,%ù) | inc %ù } } => 438ms

alias f.t { .fopen f.t " $+ mirc.ini $+ " | while !$feof(f.t) { echo -a $fread(f.t) } | .fclose f.t } => 94ms soit 4fois moins  de temps !

(le fichier mirc.ini sur lequel j'ai testé faisait environ 200 lignes seulement alors imaginez sur un gros fichier !)

? Findfile:

Cet identifieur est très souvent mal utilisé, n'oubliez pas que $findfile() revient faire une boucle pour scanner l'existence des fichiers voulus ! De plus, vous pouvez intégrer une commande à effectuer dans cet identifieur ce qui augmente la rapidité d'exécution.

ex:

alias find { var %^^ = 1 | while $findfile($mircdir,*.*,%^^) { echo -a $v1 | inc %^^ } }  => environ 1719ms

Pour augmenter la rapidité vous pouvez faire:

alias find { var %ù = $findfile($mircdir,*.*,0,echo -a $1-) }  => 171ms

? While/goto:

Lorsque vous voulez faire une boucle, privilégiez l'utilisation du while devant le goto, bien souvent celui ci s'avèrera beaucoup plus rapide.

ex:

alias t.got { var %a = 1 | :f | if %a <= 1000 { echo -a %a | inc %a | goto f }  } => environ 400ms

alias t.whi { var %a = 1| while %a <= 1000 { echo -a %a | inc %a }  } => 375ms

Cependant cette boucle reste encore assez petite, mais plus la boucle grossit plus l'écart va se voir.

Lorsque vous avez besoin de créer une boucle utilisant des identifieurs pour vous référer à une variable qui contient plusieurs chaînes de données évitez de mettre les identifieurs tels quels dans le while car sinon mIRC les évaluera à chaque retour de boucle, donc faîtes plutôt:

//var %ù = $gettok(%var,1,64), %ù! = 1 | while %ù! <= %ù { echo -a $v1 | inc %ù! }

Si vous voulez optimiser encore plus et que vous n'avez pas besoin d'avoir un ordre croissant, vous pouvez aussi utiliser la décrémentation :

//var %ù = $gettok(%var,1,64) | while %ù { echo -a $v1 | dec %ù }

? Loadbuf:

Lorsque vous voulez charger un fichier.txt dans la listview d'un dialog ou une fenêtre @win, évitez plein de /did ou /aline inutiles, préférez utiliser la commande /loadbuf !

ex:

alias l.buf { if !$window(@test) { window @test } | set %ù $sfile($mircdir\,Choisir le fichier à ouvrir:) | if %ù { loadbuf @test $shortfn(%ù) } }

Ceci sera beaucoup plus rapide que de faire une boucle qui va lire chaque ligne pour la réécrire dans le dialog ou la @win.

? Didtok:

Lorsque l'on crée un dialog avec un combo, souvent l'on voit une multitude de /did -a $dname <id> texte pour remplir ce dernier, (souvent dans les dialogs pour faire des addons de 'couleurs'). A la place, pensez à utilisez la commande /didtok $dname <id> <N> texte

ex:

//didtok $dname 1 44 Action,Créer une table,Détruire une table,Charger une table,Sauvegarder une table,Ajouter un item,Effacer un item,Modifier un item,Rechercher un item

Vous gagnerez en clarté et en rapidité car vous n'effectuerez plus qu'une seule action.

? On dialog:

Dans le même esprit que pour le didtok et toujours dans le dialog, au lieu d'utiliser plein de 'on dialog', regroupez les! Cela facilitera la relecture de votre code et le cheminement des informations. Pour cela utilisez l'identifieur $devent qui retourne le type d'action effectuée:

ex:

on *:dialog:test:*:*:{
if $devent == init { didtok $dname 1 64 <texte1>@<texte2>@<texte3>@<texte4> } ( ;) )
if $devent == sclick { if $did == 2 { did -r $dname 3 } }
if $devent == edit { $iif($did == 3,var %^ = $did($did),did -r $dname 3) }
etc...
}

? Isnum:

Lorsque vous voulez faire une condition pour évaluer si un nombre est bien dans une plage de nombres, au lieu d'avoir un code de la forme:

//var %^ = <nombre> | if %^ isnum && %^ > 5 && %^ < 50 { return $true }

vous pouvez faire:

//var %^^ <nombre> | if %^^ isnum 5-50 { return $true }

Vous gagnerez en clarté du code, puis cela permet à mIRC de n'effectuer qu'une seule condition au lieu de trois ci-dessus.

? Replace/remove:

Lorsque vous utilisez les identifieurs $replace() et $remove(), pensez au fait qu'il n'est pas nécessaire de les imbriquer les uns dans les autres, le fait de séparer ce que vous voulez retirer ou changer par des virgules fait que l'identifieur va appliquer vos besoins !

cela donne :

//echo -a $remove(<chaine de texte>,N1,N2,N3,......)

//echo -a $replace(<chaine de texte2>,e,?,o,0,....) => dans chaque groupe de 2 chaînes par exemple 'e' et '?',
le premier sera remplacé par le second, en l'occurrence 'e' sera remplacé par '?' et 'o' par '0'.

ex:

//echo -a $remove(je tape du texte pour tester,p,t) => retournera: 'je ae du exe our eser'

//echo -a $replace(<nick> <test> <heure>,<heure>,$time,<nick>,$me,<test>,$date) => retournera tofu 01/06/2005 13:32:36

? $()/$eval():

Lorsque vous avez des variables de la forme '%<pseudo>.<chan>' par exemple pour pouvoir retourner la valeur contenue dans une variable de ce type, l'on ne peut pas simplement faire:

ex:

//if $+(%,<pseudo>,.,<chan>) == 1 { }

Car la condition regarderait juste si %<pseudo>.<chan> est égal à 1 ce qui n'est pas le cas. Pour pouvoir retourner la valeur de cette variable nous devrons faire:

//if $($+(%,<pseudo>,.,<chan>),2) == 1 { } ou //if $eval($+(%,<pseudo>,.,<chan>),2) == 1 { }

? $istok():

Lorsque vous voulez faire une condition faisant une recherche dans une liste ou une condition ayant de multiples 'ou' (symbolisés par '||'), au lieu de faire:

//if $nick == pierre || $nick == paul || $nick == jacques { return $true }

Vous pouvez faire:

//var %ù = pierre,paul,jacques | if $istok(%ù,$nick,44) { echo -a $true }

Le $istok() revient à faire une boucle pour scanner chaque chaîne qui se trouve entre les tokens pour voir si elle est égale à la valeur recherchée.

Max_62 a effectué un test sur une boucle while avec des 'if' puis la même boucle mais avec un $istok(), voyons le résultat:

alias testou { var %i = 1 | while (%i <= 20000) {  if (%i == 1 || %i == 2 || %i == 3 || %i == 5) { inc %i } | else inc %i  } } => Effectué en 2854ms
alias testistok { var %i = 1 | while (%i <= 20000) { if ($istok(1.2.3.5,%i,46)) { inc %i } | else inc %i }  } => Effectué en 1693ms

Le résultat de rapidité est flagrant, l'utilisation de $istok() a permit de diviser le temps d'exécution par 2 de la boucle.

- Events

? Préfixes:

Au lieu d'utiliser plein de conditions bien souvent inutiles à part si vous voulez regroupez (pour un thème par exemple) vos events, pensez à vous servir des préfixes des events. Prenons l'exemple du 'on join':

Lorsque vous voulez qu'une action soit effectuée uniquement si c'est vous qui entrez dans un salon
On pourra remplacer: On *:join:*:{ if $nick == $me { } } , Par: On me:*:Join:*:{ }

Lorsque vous voulez qu'une action soit effectuée uniquement si c'est une autre personne que vous qui entre dans le salon
On pourra remplacer: On *:join:*:{ if $nick != $me { } }  , Par: On !*:Join:*:{ }

Et lorsque vous voulez qu'une action soit effectuée seulement si vous êtes 'op' lorsque quelqu'un rentre dans le salon
On pourra remplacer: On *:join:*:{ if $me isop $chan { } } , Par: On @*:Join:*:{ }

? Ordre:

Lorsque pour une raison ou une autre vous avez besoin de mettre deux fois le même event dans un fichier remote, souvenez vous que la place que vous leur attribuez est importance, de ce fait, placez toujours l'event le plus général à la fin. Nous allons tester avec deux 'on text'

ex:

On *:text:*:*: { echo -a event général }
On *:text:*test*:*: { echo ?a event plus précis }

Si vous les mettez dans cet ordre, lorsque quelqu'un va parler sur un salon quelconque, même si il dit le mot 'test' du second event, vous aurez seulement 'event général' en echo, car mIRC lit le code du haut vers le bas (ce qui paraît logique)

Pour éviter ceci, mettez vos event dans l'autre sens !
On *:text:*test*:*: { echo ?a event plus précis }
On *:text:*:*: { echo -a event général }

Et là, lorsque quelqu'un dira le mot 'test' mIRC vous affichera 'event plus précis' tout en continuant de vous afficher 'event général' le reste du temps.

? On text/input:

L'on voit souvent dans les 'on text' plein de 'if' pour gérer les modes, cependant si l'on regarde d'un peu plus près, l'on peut s'apercevoir qu'il  existe une méthode beaucoup plus simple pour faire cela:

"$remove($nick($chan,$nick).pnick,$nick)" => retourne le mode de la personne,

Et combiné avec un petit $iif() l'on peut faire gérer les privés et les salons le tout en un seul 'on text' de 3/4 lignes !

ex:

on ^*:text:*:*:{ var %i = $remove($nick($chan,$nick).pnick,$nick)
$iif($left($target,1) == $chr(35),echo $target $+([,$c($b($iif(%i,%i,$chr(35))),7),]) $+($u($nick),:) $1-,echo $window($nick) $+($u($nick),:) $1-)
halt
}

Et l'on peut construire le on input de la même façon:

On 1:input:*:{ if ($left($1-,1) != $chr(47)) || ($ctrlenter == $true) { var %i = $remove($nick($chan,$me).pnick,$me)
$iif($left($target,1) == $chr(35),echo $target $+([,$c($b($iif(%i,%i,$chr(35))),7),]) $+($u($nick),:) $1-,echo $window($nick) $+($u($nick),:) $1-)
.msg $target $1-
halt
}
}

De plus (merci fjxokt) lorsque l'on veut faire un bot avec des commandes dans le style !commande, il est préférable de faire un 'on text' combiné avec un fichier.ini ce qui permettra d'avoir une seule condition à scanner:

on *:text:*:#:{ if $readini(fichier.ini,section,$1) { $v1 } }

-  About

- tofu
- Remerciements: Pada, Xn, Fearless, Max_62, fjxokt
- Contact: #eXagon - irc.exagon.org
- http://eXagon.org

Conclusion :


Pour toute remarque: tofu.xdb@gmail.com

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.