FastCGI binding or implementation?

Adam D. Ruppe destructionator at gmail.com
Tue Oct 18 11:21:05 PDT 2011


Tale time, only tangentially on topic.


Today, I was coincidentally switching one of my work apps from
standard CGI to Fast CGI.

Almost trivial. Set up Apache, then build the program with
-version=fastcgi. Done.

Well, not 100% done. I had a piece of static data in the app
that worked correctly before but now means subsequent requests
were out of it.

Changed that to an instance variable, and boom, works perfectly.


* If you are using Fast CGI, avoid static variables.



The next thing is speed. From principles, there's very little
reason for FastCGI to actually be faster than normal CGI - the
startup costs are insignificant next to the total app runtime
and network lag. (Startup is maybe 5 ms on the live server,
with runtime close to 50ms and ping to the user another 100ms.
The "cost" of CGI is roundoff error in the actual deployment.)


My benchmarks supported this for the kind of loads we had before.


But now, the number of concurrent users is picking up. The CGI
still performed very well, though every so often, users complained
about lag on some resources.

I ran a benchmark comparing cgi to fast cgi with a very large
number of concurrent users.

It showed better availability and about a 15% speed boost under
this load. Since Apache restarts it when it segfaults, reliability
ought not to be affected, though it's too soon to say for sure.


So, I changed the makefile to say "-version=fastcgi" and soon
realized I must search for static variables - found just one,
so easy fix, and we're up on fastcgi.


... but that 15% in the benchmark hasn't translated to a big change
in the live environment yet. Been several hours now, and we've
been trying to force the availability issue, and failed so far.

Looks like a win, but not a very big one. Speed on the whole -
unaffected. The difference is roundoff error once you factor in
network lag and such again.



So, how can we speed up the application? The key here is client
side caching.

Using my cgi.d, there's a function:

cgi.setCache(true);

which tells it simply to cache the response forever. It makes
an expiration date long in the future.

Set that for any content which changes infrequently - css,
javascript, images, any kind of (conceptually) pure or static data,
etc.

Now, your code doesn't run again and the user doesn't hit the
network again. What was 150ms is now < 1ms. The users will feel
the difference.

You might set even data that changes often to cache for a few
minutes. Odds are the user doesn't need it to revalidate on the
server every minute. cgi.d's setResponseExpires can help here,
just set it a little bit in the future.

If the user hits a link to go back to a page then, it will
load from cache most the time, making navigating the site feel
snappy. Until the time expires, then it's wait again, but IMO
some cache is better than none.

Remember: you can cache AJAX responses too.




What if the resource actually does change? You'll want to change
the link. When compiling, there's a __TIMESTAMP__ special token.
A quick and dirty method is to use that __TIMESTAMP__ on your
resource URLs in your html so every time you recompile, it
invalidates the user's cache.

<script src="/myapp/functions.js?{$timestamp}"></script>



A better way might be to hash the content at compile time, but
I haven't written code that can do this well enough for real
work yet.

* Caching makes a much bigger difference than just about any other
  technique. You'll still want fast code for the cold cache users,
  but as they browse your site, a good cache policy can shave
  full seconds off the experience.

  The fastest code is running no code at all.


More information about the Digitalmars-d-learn mailing list