From Jonathan Swartz

HR = hit rate
Cget = cost of get
Cset = cost of set
Ccompute = cost of compute

Utility = (Cget + (Ccompute + CSet) / HR ) / Ccompute

One of the things that attracts (some) people to CGI::Application is the availability to have stripped down super efficient web applications. One of the strengths of it (CA) is that it is versatile enough to provide different strengths to different people, so in fact, a good proportion of CA users don’t actually care about what I call lean programming — as long as you’re not doing anything fancy you can get away with creating everything for every request that comes in. So that’s why some users advocate ignoring efficiency in the early stages; CGI::Application is already a pretty lean perl application framework, so any deployment that works has a good chance of being fairly efficient.

However, it turns out there are other users who require and cater for lean programming, including many of the plugin authors. The technique is very simple — you put your persistent objects/data in class storage and your per-request objects/data in your per-request CA object. (There are many tweaks to that model, including using traditional RDBMS, no-sql tuple pools, memcache variants, CPAN wrapper modules, etc, but usually the simple flavour is all you need and is easy to implement in CGI::Application.) Look at the CGI::Application::Plugin::Authentication source code if you want to see an example of the inner workings, but that’s not necessary (and the logic flow is not terribly transparent in that plug-in). The pattern goes:

  1. Have a MyApp::Base which is a sub-class of CGI::Application and which all your MyApp (request handler) modules sub-class
  2. In that class, define your cgiapp_init method
  3. In cgiapp_init initialise all your application-wide configuration into class storage (eg %MyApp::Base::__Stash) using a guard to ensure you only do this once per perl interpreter:
    unless ($MyApp::Base::__Stash{config}) {
        $MyApp::Base::__Stash{config} = {};
        # Initialise application-wide values
        # Initialise plug-ins, using those values
        MyApp::Base->authen->config(
            # ...
        );
    }
    
  4. For each plug-in you use, check whether it caters for class access in addition to object access. eg for CGI::Application::Plugin::Authentication, use MyApp::Base->authen->config rather than $myapp->authen->config and it will do the rest for you.
  5. Then (still within your cgiapp_init) initialise any per-request data into your $myapp object:
        # Per-request initialisation
        $self->param(
            foo => 'bar',
            dbh => $MyApp::Base::__Stash{db_accessor}->connect,
            # ...
        );
    

You can take this further by ensuring as much as possible is done in the initial (parent) perl interpreter, for example doing initialisation before the first fork if using mod_perl2 with the ‘prefork’ MPM, but that’s the subject of a separate story.