MacNOMODO

Où on cause du Mac - A consommer sans modération

 
PortailPortailAccueilRechercherRechercherFAQS'enregistrerMembresConnexion

Partagez | 
 

 Numbers : accélérer l'exécution des scripts

Voir le sujet précédent Voir le sujet suivant Aller en bas 
AuteurMessage
TG
Légende vivante
Légende vivante
avatar

Nombre de messages : 5498
Age : 53
Planète : Paradis n°2
Matos : MacBook Pro Unibody 2.54 late 2008 Mountain Lion • MacPlus • PIXMA iP4300 • Scanner Epson Photo 330
Date d'inscription : 12/11/2006

MessageSujet: Numbers : accélérer l'exécution des scripts   4/19/2010, 21:48

L'exécution des scripts AppleScript avec Numbers n'est pas franchement un modèle de vitesse. Pour être franc, on a tout le temps d'admirer et de comprendre ce qui se passe.

Prenons un exemple.
Lançons Numbers et créons un nouveau document. Retaillons la tableau de façon à ce qu'il fasse dix colonnes et trente lignes.

Ouvrons l'Éditeur AppleScript et lançons ça :

Code:
-- version 1
tell application "Numbers"
   set debut to (current date)
   activate
   tell document 1
      repeat with s from 1 to the count of sheets
         tell sheet s
            repeat with t from 1 to the count of tables
               clear every cell of table t
               tell table t
                  repeat with c from 1 to the count of cells
                     if c = 1 then
                        set the value of cell c to "=alea()"
                     else
                        set the value of cell c to ¬
                           "=" & the name of cell (c - 1) & "/10+alea()"
                     end if
                  end repeat
                  repeat with c from 1 to the count of cells
                     set the value of cell c to 1
                  end repeat
               end tell
            end repeat
         end tell
      end repeat
   end tell
   set fin to (current date)
   activate
   display dialog (fin - debut)
end tell

Sur ma machine, ça prend 59 secondes.
En fait, à chaque modification de cellule, Numbers recalcule les tableaux visibles.
Donc, plus il y a de cellules qui dépendent de celle qu'on modifie, plus le temps de recalcul est long.
C'est ce qui se passe quand on fait la deuxième boucle (et, dans une moindre mesure, lors de la première).

Je me suis dit qu'on gagnerait peut-être en temps d'exécution si on pouvait mettre au premier plan une feuille sur laquelle n'aurait lieu aucune opération. Voici le code :

Code:
-- version 2
tell application "Numbers"
   set debut to (current date)
   activate
   tell document 1
      set masksheet to make new sheet
      set the value of cell 1 of table 1 of masksheet to "Patientez..."
      repeat with s from 1 to the count of sheets
         if sheet s is not masksheet then
            tell sheet s
               repeat with t from 1 to the count of tables
                  clear every cell of table t
                  tell table t
                     repeat with c from 1 to the count of cells
                        if c = 1 then
                           set the value of cell c to "=alea()"
                        else
                           set the value of cell c to ¬
                              "=" & the name of cell (c - 1) & "/10+alea()"
                        end if
                     end repeat
                     repeat with c from 1 to the count of cells
                        set the value of cell c to 1
                     end repeat
                  end tell
               end repeat
            end tell
         end if
      end repeat
      try
         delete masksheet
      end try
   end tell
   set fin to (current date)
   activate
   display dialog (fin - debut)
end tell

Bingo ! Il ne faut plus que 8 secondes.
Bon, le code est un peut plus compliqué puisqu'il faut soigneusement éviter de toucher à la feuille de masquage dont la présence n'est que temporaire.

Au demeurant, ceux qui ont déjà programmé Excel en VBA savent qu'il existe des moyens d'empêcher le recalcul le temps du traitement et qu'on peut éviter la mise à jour de l'interface pour booster l'exécution du code.
On est un peu dans une problématique du même genre.

Bref.

Je me suis ensuite demandé si on gagnerait encore du temps en cachant Numbers le temps du traitement :

Code:
-- version 3
tell application "Numbers"
   set debut to (current date)
   activate
   -- la ligne suivante est optionnelle et n'apporte pas grand chose
   tell application "System Events" to keystroke "h" using {command down}
   tell document 1
      set masksheet to make new sheet
      set the value of cell 1 of table 1 of masksheet to "Patientez..."
      repeat with s from 1 to the count of sheets
         if sheet s is not masksheet then
            tell sheet s
               repeat with t from 1 to the count of tables
                  clear every cell of table t
                  tell table t
                     repeat with c from 1 to the count of cells
                        if c = 1 then
                           set the value of cell c to "=alea()"
                        else
                           set the value of cell c to ¬
                              "=" & the name of cell (c - 1) & "/10+alea()"
                        end if
                     end repeat
                     repeat with c from 1 to the count of cells
                        set the value of cell c to 1
                     end repeat
                  end tell
               end repeat
            end tell
         end if
      end repeat
      try
         delete masksheet
      end try
   end tell
   set fin to (current date)
   activate
   display dialog (fin - debut)
end tell

Ce n'est pas ultra formidable mais on gagne encore 2 secondes.
Sur un traitement plus important, ça peut faire la différence.

Maintenant, recommençons les mêmes opérations en enregistrant au préalable le script dans le dossier des scripts Numbers et lançons-le depuis le tableur.
On obtient les temps suivants :
  • version 1 : 66 secondes
  • version 2 : 19 secondes
  • version 3 : 18 secondes
Bigre ! Il est donc plus long d'exécuter un script depuis l'appli que depuis l'éditeur. Why ? I just don't know.
J'avais déjà remarqué ça.

Mais devoir ouvrir le script dans l'éditeur juste pour l'accélérer, c'est contraignant.

J'ai essayé de le lancer depuis le Terminal pour voir :

Code:
osascript ~/Library/Scripts/Applications/Numbers/test.scpt

Super ! On revient aux temps constatés dans l'éditeur.
J'ai donc créé un second script d'emballage :

Code:
do shell script "osascript ~/Library/Scripts/Applications/Numbers/test.scpt"

En l'appelant depuis Numbers, comme il sous-traite le boulot au processeur de scripts, on ne constate plus de baisse de régime. Cool !

Mais devoir gérer deux scripts, quelle plaie.

Heureusement, les ressources de l'imagination sont sans limite...

On peut demander au script de se sous-traiter lui-même à osascript.
Il faut quand même éviter que ça ne boucle ; il va donc s'appeler avec un paramètre disant qu'il s'est appelé pour éviter qu'il ne s'appelle à nouveau.
Donc, quand on l'appelle, il s'appelle sans faire le boulot de façon à faire le boulot sans s'appeler. C'est clair ?

Bref, voilà le code :

Code:
-- version 4
on run argv
   if the (count of argv) is 0 then
      do shell script "osascript " & POSIX path of (path to me) & " YES!"
   else
      tell application "Numbers"
         set debut to (current date)
         activate
         -- la ligne suivante est optionnelle et n'apporte pas grand chose
         -- tell application "System Events" to keystroke "h" using {command down}
         tell document 1
            set masksheet to make new sheet
            set the value of cell 1 of table 1 of masksheet to "Patientez..."
            repeat with s from 1 to the count of sheets
               if sheet s is not masksheet then
                  tell sheet s
                     repeat with t from 1 to the count of tables
                        clear every cell of table t
                        tell table t
                           repeat with c from 1 to the count of cells
                              if c = 1 then
                                 set the value of cell c to "=alea()"
                              else
                                 set the value of cell c to ¬
                                    "=" & the name of cell (c - 1) & "/10+alea()"
                              end if
                           end repeat
                           repeat with c from 1 to the count of cells
                              set the value of cell c to 1
                           end repeat
                        end tell
                     end repeat
                  end tell
               end if
            end repeat
            try
               delete masksheet
            end try
         end tell
         set fin to (current date)
         activate
         display dialog (fin - debut)
      end tell
   end if
end run

7 secondes chrono.

On peut réemployer cette astuce de façon générique :

Code:
on run argv
   if the (count of argv) is 0 then
      do shell script "osascript " & POSIX path of (path to me) & " YES!"
   else
      -- INSERER VOTRE CODE ICI
   end if
end run

Attention : il faut que le code inséré soit déverminé sérieusement car les erreurs peuvent être masquées par ce procédé.

>> Basé sur Numbers '09 (2.0.3) et AppleScript 2.1.2


Dernière édition par TG le 1/27/2013, 11:05, édité 5 fois (Raison : Speedup AppleScript under iWork Numbers '09)
Revenir en haut Aller en bas
http://www.panoramio.com/user/616684
TG
Légende vivante
Légende vivante
avatar

Nombre de messages : 5498
Age : 53
Planète : Paradis n°2
Matos : MacBook Pro Unibody 2.54 late 2008 Mountain Lion • MacPlus • PIXMA iP4300 • Scanner Epson Photo 330
Date d'inscription : 12/11/2006

MessageSujet: Re: Numbers : accélérer l'exécution des scripts   4/20/2010, 19:25

À la lecture of the doc of the AppleScript, il s'avère que le langage a été étendu pour pouvoir s'exécuter depuis le shell.
Le truc malin a été d'indiquer, comme on le fait pour les autres interpréteurs, le processeur en tête du fichier :

Code:
#!/usr/bin/osascript
-- Exemple
return the name of me

Trop fort !

Et en procédant de la sorte, on passe directement le code à osascript sans autre forme de procès.
Il faut néanmoins, puisque c'est un script au sens du shell, prendre soin d'enregistrer alors le tout au format texte (les AppleScript conventionnels sont précompilés et enregistrés dans un format particulier) et de le rendre exécutable par un bon chmod de derrière les fagots. Ce faisant, le script est exploitable comme un autre depuis le menu dédié à l'application. Et il tourne à la vitesse nominale (le temps de la précompilation qui doit bien avoir lieu est imperceptible).

Ce qui nous donne :

Code:
#!/usr/bin/osascript
-- version 5
tell application "Numbers"
   set debut to (current date)
   activate
   tell document 1
      set masksheet to make new sheet
      set the value of cell 1 of table 1 of masksheet to "Patientez..."
      repeat with s from 1 to the count of sheets
         if sheet s is not masksheet then
            tell sheet s
               repeat with t from 1 to the count of tables
                  clear every cell of table t
                  tell table t
                     repeat with c from 1 to the count of cells
                        if c = 1 then
                           set the value of cell c to "=alea()"
                        else
                           set the value of cell c to ¬¨
                              "=" & the name of cell (c - 1) & "/10+alea()"
                        end if
                     end repeat
                     repeat with c from 1 to the count of cells
                        set the value of cell c to 1
                     end repeat
                  end tell
               end repeat
            end tell
         end if
      end repeat
      try
         delete masksheet
      end try
   end tell
   set fin to (current date)
   activate
   display dialog (fin - debut)
end tell

Là aussi, il est vivement conseillé de bien déverminer avant car les erreurs seront plus difficiles à localiser.
Revenir en haut Aller en bas
http://www.panoramio.com/user/616684
 
Numbers : accélérer l'exécution des scripts
Voir le sujet précédent Voir le sujet suivant Revenir en haut 
Page 1 sur 1

Permission de ce forum:Vous ne pouvez pas répondre aux sujets dans ce forum
MacNOMODO :: I n f o s :: Conseils, trucs & astuces-
Sauter vers: