[GastForen Programmierung/Entwicklung AppleScript Zugriff auf Listen-Elemente beschleunigen

  • Suche
  • Hilfe
  • Lesezeichen
  • Benutzerliste
Themen
Beiträge
Moderatoren
Letzter Beitrag

Zugriff auf Listen-Elemente beschleunigen

Hans Haesler
  
Beiträge gesamt: 5826

25. Sep 2002, 17:30
Beitrag # 1 von 13
Bewertung:
(3544 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Der Import von Formatierungen kann allerdings auch sinnvoll sein, da InDesign die Verknüpfung zu Texten behält. Bei kleinen Katalogen usw. können so unabhängig vom Programm z.B. Preisänderungen durchgeführt werden. Aber es ist richtig, die Import-Optionen müssen ausschaltbar sein.
X

Zugriff auf Listen-Elemente beschleunigen

Hans Haesler
  
Beiträge gesamt: 5826

25. Sep 2002, 17:30
Beitrag # 2 von 13
Beitrag ID: #417950
Bewertung:
(3543 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Vor langer Zeit habe ich folgendes Script geschrieben. Es erzeugt eine Liste der Schriften, welche XPress zur Verfügung stehen (wenn man ein Dokument anspricht, bekommt man die Liste der Schriften, welche verwendet wurden).
---
tell application "QuarkXPress 4.11"
  set fList to {}
  set fontList to font list
  repeat with i from 1 to count of fontList
    set fList to fList & name of item i of fontList
  end repeat
end tell
fList
---
Die Variable 'fList' wird als leere Liste – {} – initialisiert.
Der Variablen 'fontList' werden die Schriften, welche XPress "sieht" (die 'font list'), zugewiesen.

Dies ist aber nicht eine Liste der Namen, sondern ein "Record", welcher die Namen und die IDs der Schriften enthält, z.B. {{name:"B Times Bold", id:151}, {name:"I Times Italic", id:16075}, ...

Um die Namen auszuziehen, gibt es nur eins: mit einer Repeat-Schleife jedes Element abfragen. Ein Anfänger macht dies wie das obenstehende Beispiel zeigt. Die Liste wird zusammenstellt, indem mit dem "&"-Operatoren der Name angehängt wird. Das Problem dabei ist, dass jedesmal die ganze Liste kopiert wird. Das braucht Zeit.

Später habe ich gelernt, die Ausführung zu beschleunigen durch 'set end of aList to name of item i of fontList'. Dadurch wird jeder neue Name nur angehängt und die Liste wird nur bei jedem 16. Umgang kopiert.
---
tell application "QuarkXPress 4.11"
  set fList to {}
  set fontList to font list
  repeat with i from 1 to count of fontList
    <b>set end of fList</b> to name of item i of fontList
  end repeat
end tell
fList
---

Aber der grosse Geschwindigkeitsschub kommt erst durch Verwendung des Wortes 'my'. Dies habe ich Diskussionen der AppleScript-Users-Mailingliste entnommen:
---
tell application "QuarkXPress 4.11"
  set fList to {}
  set fontList to font list
  repeat with i from 1 to count of fontList
    set curName to name of item i of <b>my</b> fontList
    set end of fList to curName
  end repeat
end tell
fList
---
Dieses Script hat eine zusätzliche Befehlszeile: der Variablen 'curName' wird der Name des aktuellen Elementes zugewiesen. Man könnte annehmen, dass dieser Schritt überflüssig ist und die Ausführung verzögert. Aber das Gegenteil ist wahr: dies ist die schnellste Lösung.

Für das Zusammenstellen einer Liste mit 457 Elementen (auf meinem G4/800) braucht das erste Script 64 Ticks. Das zweite 56 Ticks und das dritte nur noch 14 Ticks (eine Sekunde = 60 Ticks).

Ein Problem taucht auf, wenn dieser Trick in einer Subroutine angewendet wird. Eine Fehlermeldung sagt, dass das Resultat nicht im gewünschten Typ angezeigt werden kann. Die Lösung: die Variable der Liste innerhalb der Subroutine als "global" deklarieren:
---
getFontNames()

on getFontNames()
  <b>global fontList</b>
  tell application "QuarkXPress 4.11"
    set fList to {}
    set fontList to font list
    repeat with i from 1 to count of fontList
      set curName to name of item i of my fontList
      set end of fList to curName
    end repeat
  end tell
  fList
end getFontNames
---
Ich habe diese Technik in anderen Repeat-Schleifen gebraucht und dabei noch spektakulärere Ergebnisse erzielt.

Hans Haesler <hsa@ringier.ch>


als Antwort auf: [#417949]

Zugriff auf Listen-Elemente beschleunigen

Goar
Beiträge gesamt: 395

20. Mai 2003, 09:41
Beitrag # 3 von 13
Beitrag ID: #417951
Bewertung:
(3543 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Hans,

da hast Du den Deckel der Schatztruhe ja ganz weit aufgerissen.
Von den Beispielen habe ich sehr profitiert, einschließlich der letzten Problemlösung für Subroutinen.

Neugierig bin ich aber, wie man tics misst!

Gruß, Goar


als Antwort auf: [#417949]

Zugriff auf Listen-Elemente beschleunigen

Anonym
Beiträge gesamt: 22827

20. Mai 2003, 10:52
Beitrag # 4 von 13
Beitrag ID: #417952
Bewertung:
(3543 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hi Hans,

sehr guter Tipp, denn
Zitat von Hans Haesler Ein Anfänger macht dies wie das obenstehende Beispiel zeigt. Die Liste wird zusammenstellt, indem mit dem "&"-Operatoren der Name angehängt wird. Das Problem dabei ist, dass jedesmal die ganze Liste kopiert wird. Das braucht Zeit.

ich bin einer dieser Anfänger! ;-)

happy filemaking

Armin


als Antwort auf: [#417949]

Zugriff auf Listen-Elemente beschleunigen

Hans Haesler
  
Beiträge gesamt: 5826

20. Mai 2003, 22:14
Beitrag # 5 von 13
Beitrag ID: #417953
Bewertung:
(3543 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hi Armin,

kein Problem. Waren wir alle einmal ...

Hans Haesler, hsa@ringier.ch


als Antwort auf: [#417949]

Zugriff auf Listen-Elemente beschleunigen

Hans Haesler
  
Beiträge gesamt: 5826

20. Mai 2003, 22:18
Beitrag # 6 von 13
Beitrag ID: #417954
Bewertung:
(3543 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Goar,

zum Messen der "Ticks" (= 60 pro Sekunde) braucht man die Scripting Addition "Jon's Commands 2.1.2" (von Jon Pugh).
Diese ist zum Beispiel hier erhältlich: <http://www.osaxen.com/index.php> im Ordner "Popular".

Diese Scripting Addition installieren: Auf den geschlossenen Systemordner ziehen und die Frage "Wollen Sie... usw"
mit "OK" bestätigen. Dann den Mac neu starten. Oder im Script-Editoren die Rechenaufgabe 1 + 1 eintippen und
dieses Mini-Script ausführen. Dadurch wird die Addition ebenfalls aktiviert.

Dann können in Script an den entscheidenden Stellen durch 'the ticks' die "Ticks" abgefragt werden:
---
set startTicks to the ticks
--
--hier den zu messenden Code plazieren
--
set totTicks to (the ticks) - startTicks
display dialog totTicks
---

In die Variable 'startTicks' werden die Anzahl "Ticks" seit dem Start des Macs geschrieben. Mit dem Befehl
'set totTicks to (the ticks) - startTicks' wird diese Anzahl von der gerade erreichten Zahl abgezogen und in die
Variable 'totTicks' gesetzt. Zum Schluss wird mit 'display dialog totTicks' das Ergebnis angezeigt.

Man kann natürlich auch mehrere Messpunkte einsetzen und die Variablen 'ticks1', 'ticks2' usw. nennen.

Aber Achtung (1): je nach Aufgabe kann die Zahl stark schwanken. Deshalb macht man meistens 10 Läufe, streicht das
beste und das schlechteste Ergebnis, zählt die 8 Werte zusammen und teilt das Total durch 8.

Aber Achtung (2): wenn "Jon's Commands" aktiviert ist, dann werden Dateipfade automatisch korrigiert. Das heisst,
wenn man vergessen hat den Ausdruck 'file' zu tippen, besorgt die Addition eine 'silent coercion'. Und wenn man das
getestete Script an jemanden weiter gibt, der "Jon's Commands" nicht aktiviert hat, dann kommt eine Fehlermeldung.

Aber Achtung (3): wenn "Jon's Commands" aktiviert ist, dann kann es vorkommen dass Daten fehlgeleitet werden:
PS-Files landen im aktiven Drucker statt in der definierten Ziel-Datei.

Deshalb: nach den Zeitnehmer-Läufen den Ordner "Scripting Additions" öffnen, "Jon's Commands" in den Papierkorb
befördern, diesen leeren. Dann den Mac neu starten (oder das 1 + 1 Script ausführen). Kontrolle, dass die Scripting
Addition nicht mehr aktiv ist: das obige Snippet kompilieren. Dann sollte 'the ticks' durch den "raw code"
&laquo;event JonstikC&raquo; ersetzt sein. Und beim Ausführen kommt eine Fehlermeldung.

Hans Haesler, hsa@ringier.ch


als Antwort auf: [#417949]

Zugriff auf Listen-Elemente beschleunigen

Martin Fischer
Beiträge gesamt: 12783

12. Apr 2005, 16:43
Beitrag # 7 von 13
Beitrag ID: #417955
Bewertung:
(3543 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hans,
die Scripting Addition "Jon's Commands 2.1.2" läuft (wahrscheinlich) nur bis OS 9.x. Gibt es für AppleScript OSX einen vergleichbaren Zähler?


als Antwort auf: [#417949]

Zugriff auf Listen-Elemente beschleunigen

Hans Haesler
  
Beiträge gesamt: 5826

12. Apr 2005, 17:39
Beitrag # 8 von 13
Beitrag ID: #417956
Bewertung:
(3543 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Martin,

es gibt auch eine Mac-OS-X-Version der "Jon's Commands"-Scripting-Addition.
http://www.seanet.com/~jonpugh/ Dies ist immer noch die Beta-Version vom Oktober 2002.
Der gute John Pugh hat diese Addition auf vielfachen Wunsch der Anwender &#150; aber nur
widerwillig &#150; auf Mac OS X portiert. Er sagt dazu: "Offered under the "Something is
better than nothing" theory." Weil er zuviel Zeit in die Entwicklung von InDesign stecken
muss, ist seither keine definitive "Jon's Commands"-Version erschienen.

Es gibt aber eine Alternative, welche viel feinere Resultate liefert: "GetMilliSec".
Wie der Name sagt, wird die gestoppte Zeit in Millisekunden zurückgegeben (mit
"John's Commands" sind es "nur" Sechzigstelsekunden).

Diese Scripting Addition stammt von Hideaki Iimori. Download an dieser Adresse:
http://osaxen.com/getmillisec.html

Hier ein kleines Beispiel, wie man die Zeit zwischen zwei bestimmten Stellen im Script misst:
---
set t1 to GetMilliSec
tell application "InDesign CS"
   --
   -- hier die zu stoppenden Befehle
   --
   set t2 to GetMilliSec
   set tt to t2 - t1
   display dialog "" & tt
end tell

---
Das Resultat kann man natürlich auch vor dem Anzeigen in Sekunden umrechnen. Und häufig
nimmt man auch mehrere Zwischenzeiten.

Gruss, Hans


als Antwort auf: [#417949]

Zugriff auf Listen-Elemente beschleunigen

Martin Fischer
Beiträge gesamt: 12783

12. Apr 2005, 18:11
Beitrag # 9 von 13
Beitrag ID: #417957
Bewertung:
(3543 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Prima, genau das, wonach ich gesucht habe.

Weiterhin frohes skripten.


als Antwort auf: [#417949]

Zugriff auf Listen-Elemente beschleunigen

Hans Haesler
  
Beiträge gesamt: 5826

12. Apr 2005, 21:02
Beitrag # 10 von 13
Beitrag ID: #417958
Bewertung:
(3543 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Martin,

ein Nachtrag ... Wichtig ist, dass in der Zeitspanne, welche man messen will, keine Aktionen
liegen, welche das Resultat noch mehr verfälschen können, als es das System schon eh tut.
Man muss z.B. vermeiden, dass ein Dialog gezeigt wird, den der Anwender mehr oder weniger
schnell quittiert.

Aber auch simple Vorgänge &#150; wie das In-den-Vordergrund-Holen des Programms durch ein
'activate' &#150; können Zehntelssekunden ausmachen:
---
set t1 to GetMilliSec
tell application "InDesign CS"
   activate
   delay 2
   set t2 to GetMilliSec
   set tt to t2 - t1
   display dialog "" & tt
end tell

--> 2104.0 (und auch 2108.0; 2127.0; 2165.0)

tell application "InDesign CS"
   activate
   set t1 to GetMilliSec
   delay 2
   set t2 to GetMilliSec
   set tt to t2 - t1
   display dialog "" & tt
end tell

--> 1997.0 (und auch 2004.0; 2007.0; 2012.0)

Diese (geringen) Schwankungen weisen darauf hin, dass man ein einmaliges Resultat nicht
als einzig gültiges ansehen darf. Immer mehrere Läufe durchführen und &#150; wie weiter oben
beschrieben &#150;, das beste und das schlechteste Ergebnis streichen und den Durchschnitt der
verbliebenen ausrechen.

Wenn man Glück hat, dann halten sich die Schwankungen im Rahmen. Aber es kann auch
vorkommen, dass die Ausführung mit jedem Start länger dauert. Und erst ein Neustart des
Programms bringt für eine Weile die ursprünglich guten Werte zurück ...

Gruss, Hans


als Antwort auf: [#417949]

Zugriff auf Listen-Elemente beschleunigen

Martin Fischer
Beiträge gesamt: 12783

12. Apr 2005, 21:09
Beitrag # 11 von 13
Beitrag ID: #417959
Bewertung:
(3543 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hans,

Du bist ein Perfektionist.
Das gefällt mir (und tut mir hier auch gut). ;-)

Danke für die Hinweise.
Mir kommt's da nicht so sehr auf die Millisekundengenauigkeit an.
Aber ab und an ist es interessant, zu messen, welche Variante schneller ist.

Leider kenne ich so ne Zeitmessung in JavaScript noch nicht. Sonst könnte ich auch Vergleiche zwischen den Sprachen vornehmen.


als Antwort auf: [#417949]

Zugriff auf Listen-Elemente beschleunigen

Martin Fischer
Beiträge gesamt: 12783

12. Apr 2005, 21:51
Beitrag # 12 von 13
Beitrag ID: #417960
Bewertung:
(3543 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
die JS-Lösung (Dank an Dave Saunders):

[code:1]
var myStartTime = new Date&#40;&#41;;
// Do something
var myEndTime = new Date&#40;&#41;;
var myDuration = &#40;myEndTime - myStartTime&#41;/1000;
alert&#40;myDuration&#41;;
[/code:1]


als Antwort auf: [#417949]

Zugriff auf Listen-Elemente beschleunigen

Hans Haesler
  
Beiträge gesamt: 5826

13. Apr 2005, 00:22
Beitrag # 13 von 13
Beitrag ID: #417961
Bewertung:
(3543 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Martin,

ja, was würden wir ohne den guten Dave machen?!?

Nachstehend gleichwohl ein paar Erläuterungen.

Mit 'new Date()' erhält man die Anzahl Millisekunden, welche zwischen dem 1. Januar 1970
und der Ausführung der Script-Instruktion vergangen sind. Davon lässt sich eine ähnliche
Zeitmessungs-Konstruktion, wie jene des schon geposteten AppleScripts ableiten.

Die Instruktion 'delay' sorgt hier nur für den Aufschub der Ausführung, um die zu messenden
Aktionen zu simulieren. In die Variable 't1' wird das aktuelle (Millisekunden)-Datum geschrieben.
Nach der Kunstpause wird mit 't2 = new Date()' der Knopf der Stoppuhr gedrückt. In der
folgenden Zeile wird die Differenz der beiden Werte ermittelt und der 'alert' zeigt einen Dialog
mit dem Resultat.

[code:1]t1 = new Date&#40;&#41;;
// Hier die zu messenden Aktionen einsetzen
// &#40;simuliert durch den folgenden 'delay'&#41;.

delay&#40;1000&#41;; // Kunstpause von einer Sekunde

t2 = new Date&#40;&#41;;
tt = t2 - t1;
alert &#40;tt&#41;;

// Eine Funktion zum Aufhalten der Ausführung
function delay&#40;x&#41; &#123;
 d = new Date&#40;&#41;
 while &#40;1&#41; &#123;
  mill = new Date&#40;&#41;
  diff = mill - d
  if &#40;diff > x&#41; &#123;break;&#125;
 &#125;
&#125;[/code:1]
In der Funktion 'delay()' wird der übergebene Wert (hier 1000) mit der (wachsenden) Differenz
von einmal gestoppter Zeit und der immer wieder genommenen verglichen. Sobald das Resultat
grösser ist, wird mit 'break' die Schleife verlassen und zur Stelle nach dem Aufruf zurückgekehrt.

Die Zeitmessung habe ich selber gebastelt. Für den Delay habe ich eine Vorlage von
Sean McManus ( http://www.sean.co.uk ) etwas abgeändert.

Gruss, Hans


als Antwort auf: [#417949]
X