Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Profiling a forking program

by Tardis (Pilgrim)
on Oct 15, 2002 at 11:17 UTC ( [id://205331]=perlquestion: print w/replies, xml ) Need Help??

Tardis has asked for the wisdom of the Perl Monks concerning the following question:

Hello fellow Monks, I have a program which operates in a fairly traditional manner, it accepts connections on a TCP port, and forks a process to handle them.

Trouble is, it's starting to suck, performance wise, and finding the suckage source isn't easy.

I've hunted around, but I can't seem to find anything to profile a fork-model program. Obviously I need to profile the forked processes, since they are the ones causing me the pain.

Any clues?

Replies are listed 'Best First'.
Re: Profiling a forking program
by robartes (Priest) on Oct 15, 2002 at 11:44 UTC
    Hi Tardis,

    what performance is starting to suck? Do you have high latency (i.e. it takes ages for you to get a new connection) or low throughput (once you have a connection, it's slower than ice cream sales in Antartica) or both? In the first case, your parent program (the forking server) is in trouble, in the second your actual communication routines are the culprit, and in the third case you might be looking at an OS level bottleneck (memory, I/O, network, processor, ...).

    CU
    Robartes-

      The main part of the program (that serves an actual request) has 'issues'.

      It's a web-based frontend to a DBM database. Thus, concurrent write access demands a single process locks the DBM file, and gives up it's lock after.

      While the locking is working, performance of the software for multiple users is many many times worse than one would expect, given performance when there is no contention is excellent.

      I suspect there may be some sort of lock thrashing or similar. I need to profile this main part of the program to determine what's going on.

      The profilers I've seen all want to write to a single file, which is useless for the forked program, since it will be stomped by subsequent invocations.

        Ah, so I assume you want to profile your program to see how much time it spends waiting for a lock? One way you could have a go at this, given that your profiling tools only reliably work on one process, is to run two instances of your server, but accessing the same DBM file. Of course, this assumes the locking is done externally from the program (for example with a lock file instead of a semaphore in shared memory or some such beastie).

        Assuming this is the case, than you run one instance of your server and put load on it until it starts to slow down. You then run another instance, on a different port presumably, and limit that one to one connection only (either by connecting only once or putting limitations in the forking code, heck, even by not forking at all). You can then reliably profile that server's execution. As long as you generate load on the other server instance, and hence generate contention for the lock, you should get a reliable answer from this as to whether your program spends most of its time waiting for the lock.

        CU
        Robartes-

        Locking a DBM file in that manner is going to be problematic. You're always going to run into problems - starvation, for example, where a process ends up waiting a very long time for a lock to be freed, because you have no queue ordering.

        Perhaps a solution to look up would be to have one 'thread' (fork, whatever ;) access the DBM file on behalf of the other processes: it could just lock the file, and then access it for the other threads, so immediately you gain from removing the startup cost of tieing the DBM. Another gain can then be made by 'queueing' requests - you could have an in-memory shared queue object, or perhaps a file FIFO. Obviously, you still need to lock access to this object, but since you'll be in and out of that object reasonably quickly it won't affect you as badly as something like a DBM file, and you also rule out problems like starvation.

        Obviously, I'm simply outlining something which is actually fairly complicated, but generally the fork on request model doesn't work very well in terms of scaling. You more often see the helper-thread model, which tends to scale a bit better. Given only one process can have access to the file at a time, it makes much more sense to only have one process access it :) Having that process write the answer back to the client is fairly easy, and the helper threads would make sure all requests are queued in a timely fashion.

        The other answer is to move to an RDBMS :o)

        If your web front-end is triggering writes to the DBM file, and if the quantity of additions/updates is significant, then the problem may be in the DBM module. You could try benchmarking just that part of the application, with or without multiple threads but making sure to simulate a reasonably heavy load of data to be absorbed. (E.g. I know that GDBM really crawls once you start adding data beyond a certain threshold, I think because it has to re-write its entire index at intervals.)

        But on the other hand, maybe moving to an RDBMS needn't be so far off as you seem to think -- MySql won't be that hard to install, and getting it working within your current perl/web framework might be easier than you expect. That's worth looking at, seriously.

Re: Profiling a forking program
by deadkarma (Monk) on Oct 16, 2002 at 12:52 UTC
    Try Net::Server it works very well.

    http://seamons.com/net_server.html

    Maybe try threading? Threading is stable enough to use under Win32, and I've had sucess using it under Solaris and FreeBSD.
    I have a pre-sporked-multi-threaded server that's just about ready for prime time, although it hogs up plenty of memory, the performance is great.

Re: Profiling a forking program
by Anonymous Monk on Oct 16, 2002 at 02:24 UTC
    Well, what do you mean that performance 'sucks'. Is the server slow? Is communications slow? Make sure you are exiting/reaping any process/child you are done w/. tedori

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://205331]
Approved by krisahoch
Front-paged by JaWi
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (5)
As of 2024-04-18 01:16 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found