Forum OpenACS Q&A: Re: error in rp_handler: can't read "tcl_url2file

Posted by Gustaf Neumann on
Question 1: does putting the tcl_url2file array into the :: namespace guarantee consistency across all threads (in the same way that nsv_set does in my previous message)?

no, global Tcl variables are not shared, i have left that in the way, the original implementer of the performance-mode designed it (ages ago). actually, this variables are per-request only, since these are in the global Tcl namespace, so the only caching is within a single request. Not sure, if this was the intention. I would think that a non-global Tcl namespace would be more proper (but i have not studied the so-called performance mode in detail). In general, Tcl variables have some advantages over nsvs. When using nsvs, locks are required, while in the case for Tcl variables, parallel running requests are not influenced and can run independently on e.g. different cores without any need of context switches etc.. So, if one is really concerned about performance and scalability, Tcl variables are better scalable

Question 2: Whether PerformanceModeP is on or off, it always caches these values .. Seeing as this proc is called on every single request, wouldn't it be a boost to only do this when PerformanceModeP is on?

I would not expect a "boost", rather that the difference will be hardly noticeable. On all timings are in the range of a single microsecond or below (having maybe time granularity issues). The following commands measure in the ds/shell the basic involved commands, without taking multi-threading in account (no contention on the involved mutex). The slowest call is actually "ad_conn", which is repeated in the code, The biggest improvement would be to avoid the redundant calls to ad_conn.

lappend _ [time  {if { [rp_performance_mode] } { set ::tcl_url2file(/) /foo} } 100000]
lappend _ [time  {set ::tcl_url2file(/) /foo} 100000]
lappend _ [time  {nsv_set urlpath_file / /foo} 100000]
lappend _ [time  {ad_conn url} 100000]

set _
{0.30203 microseconds per iteration} {0.29609 microseconds per iteration} {0.33538 microseconds per iteration} {1.22374 microseconds per iteration}
You mentioned that "the client complained of slow performance" when performance mode is off. Do you have some data backing this? It can't be due to the urlpath mapping.
Posted by Brian Fenton on
Thanks Gustaf, it's all starting to make more sense now. I can see that my approach was quite naive. Very interesting that ad_conn is the slowest part.

The performance issue that our client reported, that was resolved by switching on PerformanceModeP, was a page that had a lot of Javascript that made large numbers of AJAX calls (each to the same URL). This page was very slow to load (up to 4 minutes), and after switching on the parameter, it loaded in less than 10 seconds. However, I have just learned from another developer that actually there was a bug in that page that caused a multiplier effect in the number of AJAX calls, so that e.g. instead of 4 or 5 calls, there were 100s. This has now been fixed, so probably PerformanceModeP will no longer have the same strong effect, but still it makes an interesting case for the benefits of PerformanceModeP.

Of course, the downside to PerformanceModeP seems to be its interaction with this "wizard" tool. It is natural for people to wish for the optimum performance, but not at a price to functionality.

thanks again for the help

Posted by Andrew Piskorski on
actually, this variables are per-request only, since these are in the global Tcl namespace, so the only caching is within a single request. Not sure, if this was the intention.
In older versions of AOLserver, I recall that Tcl variables were NOT cleaned up when the connection ended. They remained behind, and if you wrote code that attempted to re-use an old variable, sometimes it would work, if you happened to get a conn thread with that variable already present, and sometimes it would fail, when you got a different conn thread. Does that match your memory of how things worked back then, Gustaf?

That per-thread tcl_url2file caching approach dates back at least to ArsDigita's ACS 4.2 from early 2001, and probably all the way back to ACS 4.0 or even earlier. (As I recall, the abstract path handling was introduced late in the ACS 3.x series, probably sometime in the year 2000.) Thus, the tcl_url2file cache was designed for use with AOLserver version 3.3.x or earlier, and possibly even intended to be backwards compatible with AOLserver 2.3.3 as well. Likely its original author expected that the tcl_url2file array variable would remain behind in each conn thread, for use as a cache across multiple client requests.