5 Replies Latest reply on Feb 9, 2015 6:54 AM by Dirk Becker

    CS6 JavaScript Running Much Slower than ActionScript

    mlavie Level 1

      Dear All,

      In advance of the next version of InDesign CC, which will only support HTML5 and JavaScript, I converted all of my Extension's business logic from ActionScript to JavaScript - about 20,000 lines of code.

      I am using CS6 to run my Extension, and I call my JavaScript methods from within legacy Flex/ActionScript event-handler code using this methodology:

      [Embed(source="MyJSModule1.jsx", mimeType= "application/octet-stream" )]
      private static var _myJSModule1:Class;

      [Embed(source="MyJSModule2.jsx", mimeType= "application/octet-stream" )]
      private static var _myJSModule2:Class;

      _interface = HostObject.getRoot(HostObject.extensions[0]);


      public static function Initialize()
      _interface.eval(new _myJSModule1.toString());
      _interface.eval(new _myJSModule2.toString());


      I have found that my InDesign Extension runs about 5 times slower in JavaScript than it did in ActionScript.

      Posts I read on the web seemed to indicate that JS would only be about 30% slower.

      Would the upcoming V8-based and Node.js-supporting environment be any faster?

      I really, really need help with this.


        • 1. Re: CS6 JavaScript Running Much Slower than ActionScript
          Loic.Aigon Adobe Community Professional

          Hi mlavie,


          I have no advices here but I am curious  : what is the source of your delays, UI Refreshment, gap between UI clicks & JS execution or InDesign Code execution ?


          Do you load many js libraries, heavy ones ? Maybe the extension takes a while to load all these libs in memory. Have you considered asking to the ExtensionBuilder Forum ?


          I don't want to rub salt in the wound but the drop of AIR for extensions…what a waste. Hopefully the HTML implementation will be soon ok.



          • 2. Re: CS6 JavaScript Running Much Slower than ActionScript
            mlavie Level 1

            Cher Loïc,


            Thank you for your response.


            My InDesign Extension is a system designed to build very large documents (tens of pages, each with hundreds of PageItems), based on a large XML which contains instructions of what to put on each page of the document. I have about 85 JSX files which I load with .eval() at the very beginning of loading the Extension, as per my example above. I would say that there are about 300 lines of code per file on average, with several files being as large as 4000 lines. When I refer to the slowness, I mean slowness after the 85 JSX files have all already been loaded with .eval().


            My system is strictly Object-Oriented (or to be more exact, Prototype-Oriented). In addition, I make occasional use of the Modular (and Modular Revealed) design pattern.


            I also tend to make fairly "deep" calls (in terms of depth of the call stack). I try not to have more than 100 lines of code in a method, so when I go beyond that, I break the method into several sub-methods which are called by the original method. I am often at a depth of 20 methods in the call stack.


            My system's methods tend to pass very large arrays, objects, strings and XMLs as call parameters.


            I tried producing the pages on a hidden document (document.visible = false), so that the time consumed rendering the PageItems on the pages would not effect the time consumed - and it barely made a difference. Therefore, I assume that the commands which cause PageItems to be rendered/changed/removed are not the problem.


            I should also add that I did a code-review of myself during the conversion from ActionScript to JavaScript. I noticed a lot of places that I forgot to get do a .getElements() - for example, var firstTextFrame = myPage.textFrames.firstItem(), instead of myPage.textFrames.firstItem().getElements()[0]; So I added on getElements() in all those places. Could that be slowing things down? I was told that it is always desirable to call getElements()...


            Finally, after installing my Extension on several computers in order to compare performance, I found that one computer ran the JavaScript Extension nearly as fact as the original ActionScript Extension - and that computer was the only one with an SSD drive. Interestingly, the original ActionScript Extension doesn't run much faster on SSD. My conclusion is that the use of JSX files is somehow extremely I/O intensive.


            Please let me know if I could provide you with any other relevant information. I also posted on the Extension Builder forum, but got no responses there so far.


            Merci d'avance


            • 3. Re: CS6 JavaScript Running Much Slower than ActionScript
              Dirk Becker Level 4



              at that project/code size you get at plenty points where things matter that would be irrelevant in smaller scripts. A few years ago I extended and re-architectured a similar project, by thorough optimizations we got an speed increase of roughly tenfold, of course partially eaten up by new features.


              For the beginning: rather than issuing 80 evals, for deployment I'd compile such an enormous pile of sources into a single file. For debugging, #include is much more fun.


              As you mention argument passing of large xml, that's one area where ExtendScript can seriously slow down. Besides you'll probably find a size limit of about 64k for the underlying XML. We used InDesign document XML for working data, while smaller configuration data was parsed into js objects as soon as possible. I wrote a JSX abstraction layer that would work on either kind of XML.


              Next problem - number of prototype slots. It definitely makes a difference if you have too much, I partitioned objects into cross-linked clusters, similar to the plugin object model (boss classes), the whole enchilada supported by an underlying framework that generated JSX collections etc. by a few declarations, roughly the equivalent to templates in other languages.


              At least you're using prototypes - one really big issue with ExtendScript is the explosion of object allocations when you apply the typical closure-based JavaScript style from web programming. Eliminating them was a very big effort in our rewrite, but also gave a pretty good improvement. At least ExtendScript can produce allocation statistics, use them. Also use them to find and eliminate circular link object leaks etc. A while ago I wrote a diff utility that extends $.summary(), InDesign Server also has some goodies.


              Have you noticed ESTK's profiler? Unfortunately it just gave up at our code size, probably it will also for yours. Instead I used an own profiler with several additions, e.g. I could apply the profiler selectively to some modules while already optimized modules were skipped. It really helps to know your candidates when management pressures for "quick wins" ... Where is most absolute computation time burnt, or what methods are invoked a couple 10000 times too often for your gut feeling. Again, eliminate dead code and thus reduce prototype/object slot count. When your central class has 100s properties and matching get/set methods, eliminating them one by one produces measurable improvements.

              Of course I also tracked down some offending statements where the same value was assigned over and over again causing severe text recomposition while nothing was actually changed ... You can only find such problems with exact measurements.


              Other areas of fun: under the hood (at C++ level) every temporary text expression is backed by an enormous aggregation "suite", there are many things you can do wrong there. For example these things just pile up and are rarely purged, therefor it has become common wisdom to do an occasional save() for lengthy scripts.


              Again at the XML side: if you do severe document XML (we did), there are some circumstances where text attributes will get lost/ignored. There are ways to speed up expressions underlying references to document XML, and so forth. To know when to rebuild the XML expressions or when they can be reused is a science for itself. Same goes for other objects, as you already mention getElements(). Sometimes it helps, sometimes it is just a waste of execution time.


              As you mention the advantage of SSDs: How frequently do you dump those jsx sources into ExtendScript? If you currently use the "main" session (is that possible for HTML extensions at all?), utilize persistent sessions instead - when you have eliminated your object leaks.


              There are plenty more optimizations, I probably should write a book - to be sold in about 5 copies. Unfortunately the strongest advice in its preface would be to not use ExtendScript/JavaScript at all for large scale projects, because they turn into a maintenance nightmare where other languages catch errors on compile time. Dependent on client preference I'd probably turn to Java or do the whole thing in C++, at increasing code size development speed will be roughly on par.

              • 4. Re: CS6 JavaScript Running Much Slower than ActionScript
                mlavie Level 1

                Hi Dirk,


                Thank you for your in-depth response - much appreciated. I am currently resurrecting previous versions from source control, to see exactly when the problem started. I just wanted to post my thank-you immediately - and will add additional findings in a few hours.


                In any case, I do have a few immediate clarifications for you. I am still using ExtensionBuilder 2.1 and Flex. The calls to JSX are from Flex event handlers. There is no HTML in use. Also, all my JavaScripts are loaded a single time at initialization via those multiple .eval() calls. You wrote: "How frequently do you dump those jsx sources into ExtendScript" - I am not sure what you mean by that.


                Again - thanks!



                • 5. Re: CS6 JavaScript Running Much Slower than ActionScript
                  Dirk Becker Level 4

                  Re "how frequently" - if you use that one-time initialization it should not matter. But then we had a little UI component with the CS4 predecessor of Flex panels called "PatchPanel". There the Flex->ES initialization actually took noticable time and debugging also was a pain, so we moved most of the code to a separate jsx where we could also take advantage of the main code base.