or: “Getting started with UXPScript in InDesign, and some very rough, seat of the pants speed comparisons with ExtendScript”.
2023-06-12: Important Note: the blog post below refers to InDesign 2023 18.3.
I’ve since been able to try out a prerelease of 18.4 and was shown some tweaks by Veena Datta Dasika from the Adobe team, and the timings are now very similar.
The remaining speed differences are very small and probably just statistical noise.
Repeated runs vary slightly in speed and sometimes ExtendScript gets the upper hand, sometimes UXPScript.
There are two important use cases:
– running code that accesses the InDesign DOM.
InDesign DOM access was a lot slower in UXPScript in InDesign 18.3, but will be on a par between ExtendScript and UXPScript from InDesign 18.4 onwards.
UXPScriptSparker is set up to let me to run identical script code either in an ExtendScript engine or in the UXPScript engine.
When running a script with heavy InDesign DOM interaction, my rough measurements seem to indicate that running a script in the UXPScript could be about 3 times slower than running the exact same script in an ExtendScript engine.
To help me get my head around UXPScript and how it affects the scripting landscape around Adobe InDesign, I made UXPScriptSparker.
It’s still early days, and there are a lot of loose ends to be tied and documentation to be written, but it is already working fairly well.
I started out with JSXSparker as the base, and transmogrified it into UXPScriptSparker.
I heavily restructured and rewrote large parts of JSXSparker to end up with UXPScriptSparker.
For UXPSparker, I’ve taken a similar approach, and made it possible to write shared code that can run both in ExtendScript and UXPScript.
The UXPSparker framework contains two scaffolds: an ExtendScript scaffold, and a UXPScript scaffold. These two scaffolds take care of the nitty-gritty details of each environment and hide a lot of implementation details from the main script, allowing the script to be mostly unaware of what environment it is running in.
Part of these scaffoldings are a bunch of shared libraries and APIs, which hide differences between the environments from the main script.
For example, both scaffolds provide a method
UXES.fileio.appendUTF8TextFile(), and this method works exactly the same in both scaffolds.
The ExtendScript scaffold is instrumented to use the VSCode/ExtendScript debugger, and the UXPScript scaffold can be debugged with the Adobe UXP Debugger Tool.
The useful part (i.e. the ‘meat’) of the script can be contained in one or more .js files that are written in such a way that the exact same .js file can be executed in UXPScript as well as in ExtendScript, at will.
And here is where it gets interesting: as part of UXPSparker I wrote a little sample script that stretches InDesign’s muscle a bit.
This sample script creates a bunch of colored text frames and puts some text in it. Nothing special – my main aim was to have a lot of InDesign DOM interaction.
To try this out for yourself: download the UXPScriptSparker from Github:
Decompress the .zip and navigate into the Mac or Windows subfolder, depending on your platform.
On Windows you might have to contend with some blue ‘Windows protected your PC‘ warning dialogs from Windows Defender. Click More Info and Run Anyway when that happens.
On Mac, you need to de-quarantine the software. Right-click the
initialSetupConfigApp.command and then click the Open button:
Then double-click the
SparkerConfig.exe and configure the starter code. Pick the
ColoredTextFrames option in the
If desired you can now remove the templates and retain only the generated code: navigate into the
devtools folder and double-click
Now move the UXPScriptSparker-main folder into your Adobe InDesign Scripts panel. Start InDesign and select Window – Utilities – Scripts.
Right-click User and select Reveal in Explorer or Reveal in Finder.
Navigate into the Script Panel subfolder, and move the UXPScriptSparker-main there.
You should now see the UXPScriptSparker-main appear on the Script Panel in InDesign.
Double-click either run_as_ES.jsx or run_as_UXPScript.idjs.
I used this sample script to run some speed comparisons, and got some surprising results.
My speed comparison was all about InDesign DOM interaction.
In my line of work, the speed of DOM interaction is what is important: how fast can I make InDesign (or InDesign Server) do something?
Before anything else: none of these tests are very scientific, and need to be taken with a grain of salt.
I did not account for CPU speeds, numbers of cores, or amounts of memory, so comparisons between workstations don’t provide much useful info.
One thing I found is that repeatedly I got abysmally bad timings on multiple workstations.
Resetting the InDesign preferences seemed to cure that.
Not sure what exactly is going on, but clearly it’s possible for InDesign to get into some weird state where scripts run abnormally slow.
To avoid this issue, I reset the InDesign preferences on all the machines I used for testing.
All my Intel-based workstations are reasonably specced – i.e. SSDs, 32GB RAM or 64GB of RAM, and mid-range Intel CPUs. My M1 MacBook Air is a low-level model with only 7 GPU cores and 16GB of RAM.
First surprise: I found my lowly M1 MacBook Air ran rings around all my Intel-based machines, Mac and Windows alike.
Second surprise: with this particular sample script, UXPScript seems consistently about three times slower than ExtendScript in running the exact same script.
For example, it takes around 0.5s to execute the sample script with the ExtendScript engine on an M1 MacBook Air. Running the exact same script in the same instance of InDesign on the same computer with UXScript takes around 1.5s.
An Intel MacBook Pro clocks in at 2.5s running in the ExtendScript engine, and around 7.5s running in the UXPScript engine.
On one of my Windows VM machines, I got around 3.5s (ExtendScript) vs 11s (UXPScript).
So, by my rough measurements, running this particular script with heavy DOM interaction is about 3 times slower in the UXPScript engine than in an ExtendScript engine.