Re: Suggestions for speeding up code
Re: Suggestions for speeding up code
- Subject: Re: Suggestions for speeding up code
- From: Kai <email@hidden>
- Date: Fri, 28 Feb 2003 01:35:01 +0000
on Tue, 25 Feb 2003 16:26:31 -0500, James Burns <email@hidden>
wrote:
>
This list has been very helpful since I started reintroducing myself to
>
Applescript, and I was wondering if i could impose just one more time.
Just *one* more time, James? I hope you're not planning on leaving us! ;-)
Well, it's been a few days since you posted this - and not even a nibble so
far, so I'll bite - guess you'll just have to put up with me for now!
>
I've been writing a program in AppleScript Studio (with everyone's kind
>
help) and am at the point where I'm trying to optimize my code for
>
speed. It seems that the following handler takes the most time (3 or 4
>
seconds, roughly) to read a file, and extract some stuff from it.
That's a good start. You've already identified the most serious bottleneck.
>
The file is a text file with the following format:
>
...
>
keyWord value
>
keyWord value
>
keyWord value
>
keyWord value
>
...
>
>
Some of the values are numbers, some can be full paths for files or
>
directories. I want to extract the value that follows the keyword.
>
>
Here's how I'm going about it (be gentle, please):
Relax, James. We're all pussycats around here (most of the time). ;-)
>
(Prior to this handler I've opened the file and tested it it contained
>
some text to see if it was set up right. The global "output" contains
>
the file contents...)
Great. It's always handy to have this kind of background information when
working with isolated code snippets.
Besides the performance issues about which you asked, I've also tried to
abbreviate the script slightly to (hopefully) make it a little easier to
digest.
My first query relates to the use of the variable 'output' as a global.
Unless a variable needs to be accessed by numerous subroutines, I generally
localise its use and pass its value between handlers. (In a long script,
this also helps to clarify the external value(s) required by a handler.)
I guess you were using the line <log "Started extractStuff handler"> for
either debugging or timing but, since it's obviously not essential to the
finished script, we can now probably lose it. However, your script also
tries to reset TIDs to the value of 'oldDelims', which is currently missing
(presumably because of a copy/paste slip) - so we need to set that.
I see that, to search the text, the three variables (FirstFrame, LastFrame
and FrameStep) are set to their string equivalents. These are later reset to
the values found in the text. I opted instead to use the search strings
directly - and then add the three found values to the variable 'stuffToGet'
(which I initially set as an empty list). Both methods work fine, but the
latter allows for a slightly shorter script.
Now we come to the crux of the speed issues.
Your script uses two repeat loops, one to define the keyword that needs to
be found - and another to find that keyword in the text (represented by the
variable 'output').
The first loop is necessary to search for more than one keyword. (Instead of
setting TIDs to 'return' and then looping through 'text items', it might
have been easier to simply loop through 'paragraphs' instead. However, I'm
going to suggest an entirely different method.)
It's the second, nested loop that's probably causing the greatest delay -
and this is where AppleScript's text item delimiters can be used to great
effect. Instead of isolating the value of keywords in each line of text, we
could use the TIDs to work on the entire text - which is much faster.
BTW, I've assumed that each listed keyword is separated from its value by a
tab. If that's not the case, my suggestion will need adjusting slightly. In
addition, if a keyword can't be found, the user is given the option of
continuing with an empty string in place of the missing value (which may or
may not be desirable behaviour).
Anyway, I'd suggest something like this:
===========================
to extractStuff from output
set {oldDelims, stuffToGet} to {text item delimiters, {}}
repeat with searchWord in {"FirstFrame", "LastFrame", "FrameStep"}
set text item delimiters to searchWord & tab
try
set val to output's text item 2
on error number -1728
set {text item delimiters, val} to {oldDelims, return}
display dialog "Continue with \"\" as " & searchWord & "'s value?"
end try
set text item delimiters to return
set {stuffToGet's end, text item delimiters} to [NO-BREAK]
{val's text item 1, oldDelims}
end repeat
stuffToGet
end extractStuff
set {FirstFrame, LastFrame, FrameStep} to extractStuff from output
-- do something with {FirstFrame, LastFrame, FrameStep}
===========================
I assume you already know how you're going to deal with the resulting values
(which will still be strings). In case it might be useful, I'll just mention
that strings containing file references, numbers etc. may be converted to
values of the appropriate class by using 'run script'. For example:
===========================
run script "38"
--> 38
run script "5.25 * 2"
--> 10.5
run script "alias \"Macintosh HD:James Burns:text file\""
--> alias "Macintosh HD:James Burns:text file"
-- (*will error if the item doesn't exist*)
===========================
The main difference between the two scripts is the time taken to find each
keyword's value - which, for the original, is directly proportional to the
length of the list in 'output'. For all intents and purposes, the modified
version is relatively unaffected by this - taking about the same time to
extract values from almost any list.
To demonstrate this, I've tabled below some results taken from my machine.
The first column shows how many items were in the list, while the second
indicates the time taken by the original script (compared to that taken by
the modified version). The results are expressed as an index (the time taken
by the modified version = 1 in every case).
--------------------
index: fastest = 1
--------------------
----- ---------
list slowest
count (original)
----- ---------
10 --> 5
20 --> 7
30 --> 10
40 --> 13
50 --> 16
100 --> 38
1000 --> 400
--------------------
(So if your list contained 10 items and the original handler took 5 seconds
on your machine, the modified version should do it in about a second; if
your machine extracted values from a 20 item list in 3.5 seconds, you should
now get them in about half a second - and so on...)
HTH
--
Kai
_______________________________________________
applescript-users mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/applescript-users
Do not post admin requests to the list. They will be ignored.