Did you try running the thing under a profiler? I tend to use JProfiler here and I'm quite happy with it.
The last time I did a serious performance attach on a Tapestry 3.0.3 app, by far the biggest performance bottleneck was the demon OGNL. Howard and I went round and round on that one, but the upshot is that Howard's using OGNL right, and OGNL is actually a decent reflection package (and hence faster than, say, Apache PropUtils), but it's still not native code. Given that some page renders can require literally thousands of OGNL calls (I was up at like 1800 distinct evaluations for one page), its often the bottleneck. I've pasted my OGNL performance hints below. None of it's rocket science, but aggressively following these techniques knocked about 50% off the page render time on my forms, so there's some serious performance to be gained. --- Pat Rules to Make OGNL Run Faster: **Dot Pruning: Reduce the number of "dots" in your calls. For example, lets say you had a call that read: "ognl:foo.bar.dog". That's a three-hopper as far as OGNL is concerned, requiring three times the work of a one hopper like "ognl:dog". You can make the thing run 3X as fast if your go into your page class and create a getter and setter for "dog" e.g. Public String getDog() { Foo foo = getFoo(); If (foo == null) Return null; Bar bar = getBar(); If (bar == null) Return null; Return bar.getDog(); } Public void setDog(String value) { Foo foo = getFoo(); If (foo == null) Return; Bar bar = getBar(); If (bar == null) Return; Bar.setDog(value); } What we've done is created two java stub classes that do 2/3 of the work for OGNL so it only has to make one "hop" to get at the methods it needs. Net result is it'll run 3X as fast. **Be Static: OGNL isn't smart enough to realize that a reference to a public static final object is, in fact, static. It resolves the whole thing via inspection each time. So if you want to make an expression that reads, for example: <span jwcid="@Insert" value="ognl:@[EMAIL PROTECTED]" /> It's faster to do: <span jwcid="@Insert" value="Monday" /> You're kind of Sol if you change "Monday" to "Mon" mind you, so I wouldn't switch over to literals like this until rollout time, but it does make a difference. **Avoid Putting Components Inside Foreach: There's a lot of OGNL grinding going on behind the scenes to support a foreach, and even more ognl grinding going on to call a component. So if you put the one inside the other, well, CPU cycles burn. So in many cases: <span jwcid="@Foreach" source="ognl:listOfDogs" values="ognl:currentDog"> <span jwcid="@DogDisplay" dog="ognl:currentDog"/> <span> Is *dramatically* slower than moving the foreach down into the DogDisplay component e.g. <span jwcid="@ListOfDogsDisplay" listOfDogs="ognl:listOfDogs" /> And then combing the foreach and the dogdisplay logic inside of one component. Otherwise every time the sub component gets called there's at least one ognl set/get pair being executed to push data into the component and pluck it out again. Basically pretend you're working in a system which has *really* inefficient method call overhead and view components as methods. Then optimize to reduce method calls. **Notes: If you do your own profiling, one warning I do want to give is that on JProfiler at least, it can "hide" the true culprit in the bowels of the call stack. So if you have an ognl expression that reads "ognl:foo.bar.thisMethodTakesForever", it'll show up as a lot of CPU time belonging to ognlGet until you dive into the call stack and get to whatever's at the pointy end of the get. Most of the time the actual get is trivial so all the time really is going into OGNL, but sometimes if you have expensive gets (or sets) it can make OGNL look worse than it is. > -----Original Message----- > From: Shannon, Andrew [mailto:[EMAIL PROTECTED] > Sent: Tuesday, February 14, 2006 9:40 PM > To: Tapestry users > Subject: RE: Optimization Questions > > Hey Geoff, > > Thanks for the time put into your response. I'm glad to hear that my > fears on page/component loading are hopefully not necessary. We've been > profiling with Mercury which is great. Our bottleneck definitely > appears to be the web tier, so I agree we have more to learn on how to > leverage Tapestry better. The interesting thing is our apps run great > up to around a few hundred concurrent users. But as I mentioned it > crawls at the thousand plus mark. Preliminary results showed us a > component or two to optimize, but we're also seeing serious latency in > the ApplicationServlet. I'll be interested to see what the data really > means and what it can point to in our apps. Thanks again. > > - Andrew > <snip> --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]