Summary: I had two ideas that seem like they might significantly improve the performance of WP Super Cache under heavy comment posting load, minimizing or eliminating the need for lockdown mode. Feedback would be appreciated.
Details: One of our customers has a fairly busy WordPress / WP Super Cache site that has an extremely large number of comment posts. It's not unusual to see posts garner 500 comments within three hours, for example (a new comment every 20 seconds), and posts with more than 1000 comments aren't unheard of.
The site uses a great many WordPress plugins. An uncached page load can take several seconds, even on an otherwise lightly loaded (90% idle CPU) 3 GHz dual Xeon server using FastCGI.
With this kind of comment posting, even WP Super Cache can't really keep up unless it's in lockdown mode. The customer is unhappy with that because of the delay in comment posting.
So I analyzed this. Consider what happens when a comment is posted if lockdown mode is not enabled: As a first step, the supercached file is removed. The blog then regenerates the supercached file the next time it's viewed.
However, if the page is getting several views per second, this causes a problem. The instant the supercached file is removed, the load on the server shoots up, because several concurrent requests for the uncached page arrive and start running. Within a couple of seconds, there might be half a dozen copies of the script running, all competing with each other for resources to display the page (and generate the cached file as a side effect). And there are more requests arriving every second, making things worse and worse. Sometimes, the resource contention can cause the first WordPress copy to take ten seconds or more to regenerate the cached page, and even after the cached page is first generated, the server is almost certain to be "pegged" for twenty seconds or more finishing up the requests that arrived.
Then, 20 seconds later, the whole thing starts again with a new comment post. The end result is that more than half the time, there's no cached page available, and the server will pretty much be 100% busy running WordPress scripts despite the caching, leading to errors as it runs out of CPU time.
Lockdown is the traditional solution to this. But what's interesting is that the performance problem is not caused by the *first* post-comment visitor requesting a new page and regenerating the cache. The server could handle regenerating the new cached page once every 20 seconds as a new comment arrives, no problem at all. Rather, it's caused by the fact that there might be *dozens* of new uncached requests for that page before the supercached copy is regenerated.
If WordPress could be made to run the code to regenerate the cached page only once per comment post, this shouldn't be a problem (and almost nobody would need lockdown mode).
I had two separate ideas about how to make this happen. First of all, it might be possible for WP Super Cache to realize that a page is in the process of being regenerated by another concurrent process, and simply wait a few seconds for the result of that page to appear in the cache directory, and send that back instead of running another full WordPress instance. This could be implemented as follows:
When a request for a "to be cached" page starts, WP Super Cache would put a special temporary file with a funny name in the appropriate supercache directory. At the beginning of each request, WP Super Cache would check for the existence of this file. If the file is present and is less than, say, 15 seconds old, the code would go into a loop where it sleeps for, say, a tenth of a second and looks to see if the cached file is now in the directory. If so, use it. If we've slept for more than what would be 15 seconds since the temp file was created, assume that something is wrong and break out of the loop and run normally.
A second idea is to not delete the "obsolete" supercached file when a new comment is posted. Instead, rename it to a special name -- say, append ".obsolete" to it. The .htaccess rules won't find the file under this special name, so the next request will start regenerating the supercached file. However, that request could check to see if there is a ".obsolete" file present in the directory, and whether that file is less than, say, 30 seconds old. If so, rename it back (remove the ".obsolete") so that subsequent requests that arrive for the page before our process finishes will still use the original cached file via the .htaccess rule. Again, our process will be the only one regenerating the new file, running no more than once every 30 seconds.
This second idea isn't perfect, because it delays the appearance of the most recent comments (like lockdown mode) if two people do visit the page at once. However, the average delay is the same as the average time between requests for the page, and the maximum delay would be 30 seconds (or whatever), which is much less than lockdown mode.
So those are my ideas. Any thoughts? I suspect I might be missing something obvious. If either of these sounds like it would work, I can come up with a patch and test it.