Application Object Replacement

Do you have a question? Post it now! No Registration Necessary.  Now with pictures!

Threaded View
I need an Application object replacement. I was creating my own using
shared memory -- shm* API in PHP. I was doing fine for 6 months until
it just got too fat, I guess, and the RH9 Linux server just started
"losing its memory". I don't know -- perhaps I'm doing something
wrong, perhaps it's my code, or perhaps there's a limitation on what
I'm trying to do here. It's too many lines of code to debug right now.
I'm searching for alternatives.

The reason I was using this was because it sped up things so that
instead of a database hit, my pages hit server memory for small things
like caching reference tables that translate usernames to email
addresses, group codes to group descriptions, and so on.

Of course it's a dangerous thing to use an Application object in a
server farm, so what I do is I refresh it on every server upon user
login to the website. It hits the database and pulls the latest data
to populate that server's Application object. If I update a reference
table, I also have a script that refreshes this on every server. So,
there's like a 99.9999% chance that everyone's going to have the
latest Application object data.

....that is, until it got too fat, I guess.

Anyway, does anyone have any ideas on how to use a different technique
like environment variables; a socket service that caches the array to
RAM after reading it from a database every 15 minutes; or other

I could store the entries in a file, but the point is that I don't
want disk access here -- I want it in RAM.

My Linux server has 1GB of RAM. I calculated the shared memory stuff
I'm storing there and it's no more than 20MB.

Re: Application Object Replacement

Google Mike wrote:
Quoted text here. Click to load it

Linux, indeed most forms of *nix are phenomonally good at cacheing file i/o
therefore if you store the stuff in files it will most likely be available
from 'RAM'. Indeed this is likely to be even faster than running a DBMS off
a ramdisk. The only time I would even consider using shm is when I need
manage near concurrent access to data which is rapidly changing - and I
guess that is not the situation here.

Try it.

You can virtually eliminate file i/o by switching off atime on the relevant

Or of course you could put the files in a ramdisk, but there's not a lot of
a performance gain there.



Re: Application Object Replacement

Quoted text here. Click to load it

Hmm. Didn't think of that. Sounds like you're on to something.

What about creating another filesystem with a portion of my Linux's
existing (ext3) file system? Is that possible? If so, could I then
apply the switch on that second file system to turn off anything that
might slow it down? Can I make it a faster file system instead of
ext3? If so, then I could do reads from this second, super-fast
filesystem and perhaps get the kind of speed I need? What do you

Re: Application Object Replacement

Because I was having upper limit memory limitations in Shared Memory
API on RH9 Linux, I found a better option for Linux than Shared Memory

mkdir /mnt/tmpfs
mount -t tmpfs -o,mode=770 tmpfs /mnt/tmpfs
touch /mnt/tmpfs/application_object.db

....and now, if I create the application_object.db as a key=value pair
file (like an INI file), I can read and write to it in PHP extremely
fast because this uses Linux virtual memory. Linux virtual memory is
pretty much like virtual memory on most operating systems -- you use
RAM to a certain extent and then you start swapping out storage to
blocks in a swapfile on the hard drive. In the command above, it has
the capacity to store almost up to all your RAM space and almost all
your swap disk space if you want it to. And, when you reboot, this
goes away.

The tmpfs filesystem is sort of like a ramdisk, but instead of being
limited by RAM, you go beyond that into available disk space on the
swapfile filesystem where you mount this. And, it's not like reading
and writing to the disk -- you're reading and writing to a cache
that's swapped out in RAM, giving you a lot more speed than normal
disk I/O.

The other advantage of using this technique besides the Shared Memory
API is that I can actually use command line to "cat" files out and see
what's in them, checking for problems I might have created in code. If
my file is corrupt, I'll be able to see it. If you have a corrupt
Shared Memory section, you can't "cat" it (that I know of) to see
what's going on. Here's another advantage over Microsoft's IIS Server
Application Object -- you can't physically inspect that object, but
here, with tmpfs on Linux, you can.

If you use this technique, then you need to probably do the following.
On computer bootup, say in a Bash script like at the bottom of
rc.sysinit, you have to recreate your tmpfs space, read those
reference tables from your database that you want to cache to optimize
your web application, and write these entries into
/mnt/tmpfs/application_object.db as key=value pairs. Then, when you
want to read these values from your PHP pages, you just do normal file
API against application_object.db. And, you can probably abstract that
code into your very own Application object class file in PHP.

However, be careful about implementing this in a web farm because each
server has its own exclusive memory. To get around that limitation,
you might want to consider first whether it's better to just read from
the database and optimize some settings on it instead of using an
Application object there. However, if you do wish to go ahead and try
it, here's some extra steps that might work in some cases for you:

1. Upon every user's login to your website, such as in a file like
login2.php, refresh the /mnt/tmpfs/application_object.db file from the
database upon the next moment your web server sees that this is not
being read from or written against. (I would recommend this, anyway,
even in a standalone web server environment.)

2. If you administer the reference files in your database that you
were trying to cache, then you need to create a Bash script that you
can call to tell all your web farm servers to refresh their
application_object.db objects from the central database the next
moment the web server is idle.

Re: Application Object Replacement

An even better step on the road to replacing a custom Application
Object class in Linux-based PHP, getting away from Shared Memory API
(shm*), is to use tmpfs and read/write to that as I mentioned
yesterday in this group. I found a neat way to autoload this and have
a way to restart the service when you need to do so. The technique is

# stick me in /etc/init.d as file named "webcache"
#! /bin/bash
# webcache          Start/Stop the Web Cache
# chkconfig: 2345 90 60
# description: webcache is a tool designed to give web developers \
#              a hot settings file /mnt/webcache/settings.db where \
#              they can store application settings, caching stuff so \
#              that they do not need to hit the database.
# processname: webcache
# pidfile: /var/run/

# Source function library.
.. /etc/init.d/functions

start() {
    echo -n $"Starting Web Cache: "
    mkdir /mnt/webcache 2>/dev/null
    mount -t tmpfs -o mode=770 tmpfs /mnt/webcache 2>/dev/null
    touch /mnt/webcache/settings.db 2>/dev/null
    echo "key=value" >> /mnt/webcache/settings.db 2>/dev/null
    touch /var/lock/subsys/webcache

stop() {
    echo -n $"Stopping Web Cache: "
    umount /mnt/webcache 2>/dev/null
    rm -f /var/lock/subsys/webcache

rhstatus() {
        if [ -f /var/lock/subsys/webcache ];  then
        echo "webcache started"
        echo "webcache stopped"

restart() {

reload() {
    echo -n $"Reloading Web Cache: "

case "$1" in
      [ -f /var/lock/subsys/webcache ] && restart || :
    echo $"Usage: $0 "
    exit 1

exit $?

....Then, do this at command line (once you are root):

/sbin/chkconfig --add webcache

Now you can see "webcache" in Services Control Panel on RH8 or better
Linux, and you can start and stop it, or set it to automatically start
when the computer starts up. It also provides a default text file
called /mnt/webcache/settings.db that you can read/write to from your
PHP code.

To improve this script even more, you can use Bash and have it read a
settings from a file you can create called
/etc/webcache/webcache.conf. This file can then have SQL statements in
it that you can read, run, and then store the results in
/mnt/webcache/settings.db as key=value pairs. And you can create a PHP
class called Application that reads these pairs from any web page.

Re: Application Object Replacement

I'd like to criticize my earlier submission about building a RAM cache
using tmpfs on Linux, or even using a ramdisk file system. It's all
interesting and everything, but I saw no significant speed improvement
compared to just reading from a settings file. Linux simply does an
outstanding job already with normal file I/O after multiple hits to
the file. I now use a technique where my Application object class just
reads from a settings file. To update that settings file of key=value
pairs, I wrote a regen.php page that reads cache.conf (something I
came up with) that tells it what SQL to read and cache in a file
called cache. Every time someone administers these reference tables
that are used in the cache, I make a call to regen.php to rebuild the
cache. Okay, so what about the problem where someone reads from the
cache the moment I'm rebuilding it? No problem. I drop a busyfile
there to let me know, and the Application object class automatically
knows to use the last backup of this cache file instead of the latest
one, until the busyfile is no longer there.

So, key points I learned:

* In cases where this is suitable, do you want to cache stuff from the
database so that your PHP web pages run faster? Fine, use a settings
file and read from it with normal file I/O. It will run just as fast
as a ramdisk or tmpfs filespace. If you use Linux, it will load very
fast and multiple people can read the same file at the same time. You
can then abstract the file I/O with your own Application object class.

* Do you want to update this settings file? Fine, I use a technique
where I copy the settings file into a backup settings file and drop a
busy file. I then wait 5 seconds. This gives my Application object
class plenty of time to recognize the existence of the busy file and
start directing users to the backup settings file instead of the real
one. I then regen the settings file based on reference tables from SQL
that I want to cache. When finished, I delete the busy file so that
the Application object class recognizes that it can start using the
new settings file.

* Do you want to webfarm your Application object? This is possible
since it's file-based. You just mount NFS on each server and use a
process to distribute it (while also using the backup/busy file
process) so that the Application Object class can read the alternate
settings file while your process updates the real one.

Hope this speeds up your PHP apps!

Re: Application Object Replacement

Turns out I was wrong even still. There is a faster way to implement
application object like caching in PHP without the shm* API and
without file i/o.

Normal file i/o is fairly fast on Linux on a good system, but on a
weaker system like an 800Mhz with IDE, it's not great at all when it
gets hammered for looking up strings from a cache file. And for some
reason, using a ramdisk is only slightly faster. I guess it comes down
to the fact that PHP has slow file i/o API? I'm on 4.2.2, so perhaps
that condition is only on that version of PHP.

What does seem to work extremely fast, however, is to draw from a
class object with hard-coded properties, and include this page with
require() on the page that needs to draw from cache.

Okay, so you might wonder, how the heck do the values get in the class
object in the first place? The answer is that you regenerate this PHP
class file from a script.

So then this begs the questions:

1. When do I regenerate this PHP class file?
2. When it's being regenerated, how do users read from it without
getting an error?


1. A good time to regenerate this PHP class file is every time you
update the items that you are trying to cache. Since caching is really
only recommended for small reference tables that you draw from
frequently but which do not change frequently, then every time you
update the reference table, you can regenerate the PHP class file. I
do this from my admin pages that I designed for these reference
tables. If I leave the admin pages to return to the end user mode in
the application, I trigger regeneration automatically.

2. When the PHP class file is being regenerated, then of course this
will be a problem. You'll need to come up with a way that a file named
"busy" is detected and callers of this class file are automatically
switched over to the last backup of the PHP class file.

Re: Application Object Replacement

"What does seem to work extremely fast, however, is to draw from a
class object with hard-coded properties, and include this page with
require() on the page that needs to draw from cache."

I'd like to comment that the class file technique works because I've
put it into a production environment with several concurrent users.

Here's the details:

* I have this set of admin pages. You can edit reference tables in the
database, but they do not update the cache files that the website
uses. However, when you exit the admin pages, the exit link tells the
website to regenerate cache. (Oh, I can hear you say, "What's a
reference table?" A reference table is one you store no more than say,
100 rows (although you may store more) which has primary keys that end
up being foreign keys in other, much larger tables in your database.
Typically a reference table is not one you change very often -- say,
once a week.)

* When I regenerate cache, I first make a backup of the existing cache
file. Then, I drop a busy file. I let that busy file sit out there a
few seconds before continuing. Users, upon hitting the website, will
hit code that sees that busy file and automatically direct users to
use the backup cache.

* Next, I begin to regenerate the cache by reading a cache.conf file
to identify the SQL queries I want to cache in a format of class
properties, generating a list like:


....and then I tack on a class file header and footer (two fragments of
a complete class file) to combine everything into a real class file.
For even more coolness, this class file has methods in it (Translate
and Pull) that allow one to pull a value from the cache or translate
one row value with another (such as username with full name).

* Then, I remove the busy file and users (via my code) now start to
use the new cache. The first time they hit it, PHP compiles it.

* This makes for a superfast cache that seems to operate much faster
than me hitting the website constantly for these values. It also
allows me, for instance, to build a work order ticket that has foreign
keys, but I don't need SQL joins to translate the foreign keys -- I
can just pull them from cache.

* You see, SQL has to be parsed and translated, but a PHP class page,
once it gets compiled into bytecode the first time you hit the page,
provides an object that is much more responsive in a shorter amount of

Re: Application Object Replacement

Quoted text here. Click to load it

It is not true when disk activity is high. Cache content might get
replaced very often in such situation.

Anyway, it is not wise to rely on application object in a server farm.


Site Timeline