CF Muse Reader Asks:
I am using CFMX7 on Windows 2003. We are seeing some serious processor peaks when the Cfdocument tag takes off to write out a report. We have the latest hot fixes in place...any suggestions?
Cfdocument is a new weapon in the Coldfusion arsenal. It's not without it's detractors, but personally I think it is splendid for what it can do. When it comes to performance, however, there are a number of things to keep in mind. If you think about what Cfdocument is being tasked to do under the hood and I'm sure you could come up with a few as well. Since it is my blog, we might as well work from my list...
This issue initially caused quite a few headaches with developers. The first release of CF 7 (pre-Merrimack) had a significant bug when trying to render an image. The image would be resampled much larger on the page. Some developers discovered that setting the image to a percentage (from 65% to 75%) of the original size caused it to render nearly correct. Others came up with clever ways of dictating sizing to the image like embedding it in a table cell as a background image so that the cell properties would dicate size, as in this example:
HTML allows you to do cool things that you simply can't do in a printable document. A print document can't "expand or contract" based on the user environment. It has a finite set of boundaries. Therefore, when you think of the HTML you are going to be rendering you should take as much of the "unknown" out of the equation as possible. Try using absolute values for width and height attributes. Don't nest tables. Set margins that make sense. Use values that make sense for printing. For example, this snippet (which I confess I have not used) comes from a sample posted on livedocs.
As a developer you are not privy to this behind the scenes calculation. It happens on the client - and you are using the power of the desktop to do some of your work for you (good for you!). But Cfdocument has to play both client and server. If you use a value like 80% the rendering engine will have to work out the math. Things get more complicated when the item is nested. For example, if you produce a table that is 90% wide with a nested cell that is 50% wide and a nested table that is 90% with 2 cells that are 40% and 60% (whew) think of the process for rendering the inner most cell at 40%. If you could be a bug in your computer... er... I mean a fly on the wall in your computer.. you might hear something like this:
The final thing that comes to mind is one you may not have thought about. An HTML file is not really a self contained entity. When the page is received by the browser it does a "catalog" of all the resources needed to render that page. Then it goes out and gets all those external files - images, css, flash, Javascript etc. What you see on the page is generally a result of many separate http requests, not just the one that called the page.
A PDF file on the other hand really is a document in the traditional sense. All the resources it needs to be viewed must be embedded in the file. The only exceptions are fonts. With fonts you can choose to embed them or not embed them. If you don't embed them, then the PDF will display with whatever fonts the user has installed. If they match, the PDF will display correctly.
This "encapsulation" principle of a PDF file has implications for Cfdocument. Take the example of an image embedded in a document. Let's say I have the following:
Now consider, in the example above, how does CF knows where the file is? Answer: CF will use regular file mappings starting with the location of template containing the Cfdocument call. In other words, it treats it like a Cfinclude. Of course this causes problems at times because you don't really think of images relative to templates. You are more likely to think of them relative to the web root. So perhaps you decided on this elegant solution. You might simply convert this to an absolute path as in:
This works well. The image is rendered correctly. But consider what is going on behind the scenes. The server is:Personally, I consider this latter issue to be the most likely cause of performance problems. A slow server at the other end of a cfhttp request (even your own server) could cause a hanging thread while Cfdocument waits for the contents of that file. A PDF with a lot of external resources (like a catalog for example) would really hammer the resources of your server. DNS issues are always problematic on web servers and rarely understood.
I'm afraid I didn't answer your question in a way that points you in one direction. Still, I hope there are some clues here for you. If anyone has any other Cfdocument tips feel free to comment. Keep those questions coming.
You'll have a lot finer control over the printing than CFDOCUMENT gives you, and the performance has been decent with reports that contain nested tables and images.
I've used CFDOCUMENT and it's much, much easier than learning XSLFO syntax and quirks, however there's always a tradeoff...
Your entry on Cfdocument and Performance was excellent and really got us thinking.
We were using a giant JPG image and overlaying the data on it then wrapping it in CFDocument. (crazy I know, but very much required). It took FOREVER to render. We tried replacing the percentages with absolute values but found little relief.
Then we started experimenting with everything. We finally discovered that by simply replacing the JPG image with a similarly sized GIF we drastically reduced the time to render. In fact, we rendered 5 of these in a row, popped them all into a ZIP file, save to the server and then provided a link, in just over SEVEN SECONDS. INCREDIBLE! We're now replacing all JPGs in our CFdocuments with a GIF.
Give it a try.
Thanks!
Carmen
If you need the quality of JPG but the inclusion of them kills the CFDOCUMENT performance then either include the image as a PNG or in our case where we use CFX_IMAGECR3, we save it from JPG to PNG. It's at least 5 times quicker to display the PNG.
Throughout our investigation we also found that concurrent CFDOCUMENT executions resulting in stunningly long waits (we're using CF 7.0.2 Enterprise). Putting a CFLOCK around the CFDOCUMENT tag, so no real concurrency takes place, improved things dramatically (but won't scale very well though). Our discovery of using PNGs reduces the problem.
I have a page with a .swf CFChart (we'll call it Chart1) on it, in the background I create a .png file on the server with the same image. If the user chooses to view as PDF, the PDF includes the .png file as the image.
The .png created for Chart1 works just fine, I can open it with Fireworks or Photoshop to look at it, and it is included in the PDF and looks good.
I allow the user to drill down from Chart1 to Chart2. I use the same methodology for Chart2. I save the chart as a .png file and want to include it in its own PDF. But, in this instance I get a red-x on PDF and when I try to open the file created on the server with Fireworks or Photoshop I get messages saying its an unknown file type.
I am creating the files for Chart1 and Chart2 exactly the same, so I don't understand why one is working and one isn't. Anyone else have problems like this? Any ideas?