I am working with my Cocoa app to be scriptable by Python and Ruby using ScriptingBridge as well as by AppleScript. It is all working well, but I hit a serious issue today when I ran a long script. A python script that is fine and thoroughly checked will crash if it runs a long time. It crashes with no message to the Console or to standard error. It crashes both when I run using tools in my Cocoa app or if it is run from Terminal app. I got it to work with a script rewrite, but it raises some serious concerns.

I reduced the problem to these two loop fragments. Note: the question here is about the Cocoa ScriptingBridge and not about these python code fragments, hence the reason to post on this Cocoa list. The issue must be related to how these commands trigger Apple Events through the Scripting Bridge. In these scripts, recs is an SBElementArray with a collection of objects from my app. The methods birthSDN() and birthSDNMax() are properties of my app's Cocoa objects and thus will trigger an AppleEvent to read them.

Method 1:

for indi in recs:
    emin=indi.birthSDN()
    emax=indi.birthSDNMax()
    if emin!=0 and emin==emax:
        (code to save details on indi)

Method 2:

emin=recs.arrayByApplyingSelector_("birthSDN")
emax=recs.arrayByApplyingSelector_("birthSDNMax")
for i in range(len(recs)):
    if emin[i]!=0 and emin[i]==emax[i]:
        (code to save details on indi)

Method 1 crashes if len(recs) is above about 6000. Method 2 is much faster and has not crashed yet (but I haven't tried huge files). The idea for method 2 came from Apple ScriptingBridge documentation that recommended using [SBElementArray arrayByApplyingSelector:] whenever possible. Specifically it says:

"As a corollary to the above guideline, avoid enumerating SBElementArray objects if there are alternatives, which Scripting Bridge and Cocoa provide..."

and then mentions [SBElementArray arrayByApplyingSelector:] (and some other tools). To check if "enumerating" was the problem, I modified method 1 to be

Method 1b:

for i in range(len(recs)):
    indi=recs[i]
    emin=indi.birthSDN()
    emax=indi.birthSDNMax()
    if emin!=0 and emin==emax:
        (code to save  details on indi)

This version lasts longer than Method 1, but still crashes before long. I counted the total number of Apple Events triggered in these loops. The crashes occur in the range of 16000 to 20000 events.

My concern is that the ScriptingBridge does not scale to long scripts and will always crash if too many AppleEvents are triggered. I would be happy if method 1 was just inefficient and slow (as implied by the documentation), but it is a serious problem if inefficient (but valid) scripts are crashing. Furthermore, I am working on numerous other scripts and method 2 simply cannot be used. Thus, while I try to "avoid" method 1, it cannot always be avoided?

------------
John Nairn
http://www.geditcom.com
Genealogy Software for the Mac

_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to