PDF In-Depth

A look at CD based publishing

March 16, 2000


Performance can suffer rather alarmingly when you try to do outlandish, computation-intensive things in an interpreted language. This may seem an obvious truism. But it will only get more obvious as you expand your reach, programming-wise. JavaScript is interpreted one line at a time, by the runtime interpreter, when it executes. It is nowhere near as fast as Perl or Java, which are also interpreted but which are bytecode-driven languages. In Java or Perl, your text-edited code gets pre-cached and compiled into an intermediate representation before it goes to the runtime environment. The intermediate representation is called bytecode. It is machine-dependent code that executes midway in speed between raw BASIC and fully compiled C. The reason it runs fast is that expressions are already fully parsed, all constants are precalculated, any lexical ambiguities have been fully resolved, and in general a lot of work has been done to optimize what you've written. In JavaScript, that's not the way it works. Your plain-text code has to be parsed at runtime, and all (or most) of the above occurs "just in time." That is to say, the CPU sits and waits. There is no pre-compile. No intermediate representation of partially optimized and bound code. Just "here's the function, now let's see if it parses and can be made to work." The interpreter may "see" all of your code at load time, but it gets made into something executable on a line-by-line basis, realtime.

Performance measures

So for example, if you have built a lot of complex objects with many layers of in-between "child" objects, you've created some wicked possibilities for program slowdowns. For example, let's say you have an expression that (in JavaScript for SVG) looks like:


Which is an actual example of code that does occur, frequently, in JavaScript for SVG. (Although this is an SVG example, the same lessons apply to PDF JavaScript. So keep reading!) Well, all you're trying to do in this humongous line of code is find 'button1' and set its fill color to red. Simple enough. But look at what you're asking the interpreter to do. First, the interpreter has to get access to the top object (theDoc) and traverse its property list to see if there's an attached SVG object called 'svgTopPanel'. This calls for an array indirection of the 'hash' kind, because any time you do:


you are really doing myobject['child1'], which is how JavaScript implements all your "dot operator" child objects internally. Once the child object has been found, its properties can be accessed, the same way. So (in the above example) we next look at our svgTopPanel via the class's getElementById() method to see if it has an attached element (in its elements array) called 'button1'. If that succeeds, we call on the getStyle() method to retrieve its style object. Finally, we then use the style's setProperty() method to change the fill color.

Folks, that's a lot of indexing and node traversal just to set a darn fill color! Now imagine that you have to do this operation many times per second because some damn fool programmer has requested that an animation occur as part of an event handler. (Bad idea! Event handlers should have fast-acting code.) Do you see the problem? We're piling array indirection upon node-tree traversal upon CPU pipeline stall.

Fortunately, there is a workaround. But in our laziness as programmers (and let's face it, the very BEST programmers are best precisely because they are LAZY!) we forget that a tiny bit of attention to small details can boost program performance significantly. In the above case, what you want to do is have a function execute as part of the page's onload handler, in which hard-to-get-at objects (like that gosh-darn button's style object) and associated methods are cached in global variables. And I don't mean nicely orchestrated arrays, etc. If you're after brute performance (speed-speed-speed!), you hard-code all the global names and cache everything in sight. (Don't introduce new arrays if you're trying to get performance back!) Bottom line: When you need to set that button's fill color, you should be able to do:


Which exeutes many times faster than that gosh-awful big expression of a few paragraphs ago (see above).

Persistency of objects

One thing you do have to be wary of when using the cache-everything approach is that you really do need to sock the cachables away into persistent storage. If you stash your cache in the wrong kind of storage context or Call object, scope may be lost when you're looking the other way and the JS garbage collection mechanism may unceremoniously trash your cache. So do use your head.

Now, so; but. Imagine that your program has lots of accesses to properties like this one, maybe inside loops, etc. The multipliers are such that you can bring your whole program (or form, or SVG web page, or whatnot) to a standstill if you're sloppy about these "little optimizations" (which aren't so little, in truth).

PDF In-Depth Free Product Trials Ubiquitous PDF

Debenu Quick PDF Library

Get products to market faster with this amazing PDF developer SDK. Over 900 functions and an equally...

Download free demo

Five visions of a PDF Day

In the world of PDFs or as we like to say Planet (of) PDF, a year isn't a real PDF year without an intense few days of industry knowledge sharing.

May 15, 2018
Platinum Sponsor

Search Planet PDF
more searching options...
Planet PDF Newsletter
Most Popular Articles
Featured Product

Debenu PDF Aerialist

The ultimate plug-in for Adobe Acrobat. Advanced splitting, merging, stamping, bookmarking, and link control. Take Acrobat to the next level.


Adding a PDF Stamp Comment

OK, so you want to stamp your document. Maybe you need to give reviewers some advice about the document's status or sensitivity. This tip from author Ted Padova demonstrates how to add stamps with the Stamp Tool along with related comments.