How much do preforking and prethreading improve performance? For preforking, the advantage is clear. Because of the overhead of launching new processes, heavily loaded servers generally see a marked performance boost when going from a conventional accept-and-fork design to preforking. In fact, when I used the standard WebStone benchmark [http://www.mindcraft.com/webstone] to compare the connection rate of the accept-and-fork server of Figure 15.3 and the preforking server of Figure 15.5 on a Linux system, I saw an approximately fivefold increase in performance at heavy load levels after adjusting for the overhead of the actual file transfer. The situation is less clear-cut for threaded servers. The overhead for thread creation is not as large as for process creation, and the prethreaded design itself introduces new overhead for thread locking and synchronization. With the WebStone benchmarks I was unable to document speedup in the prethreaded server of Figure 15.9 compared to the conventional threaded server of Figure 15.8. The performance of both the threaded and prethreaded designs was better than that of the accept-and-fork server, but roughly equivalent to that of the preforking server. However, such performance is very sensitive to the operating system, hardware, kernel parameters, and other factors. It's worth subjecting a prototype of your particular application to timing tests before commiting to one design over another. Surprisingly, all the Web servers developed in this chapter came in with better benchmarks than the state-of-the-art Apache Web server (almost ninefold better at moderate load levels). Although this isn't a fair comparison since Apache does many things that the simple Web servers developed in this chapter do not, it does illustrate that Perl can deliver sufficient performance for serious network applications. On a less positive note, a side effect of the testing was to confirm that under heavy loads the threaded implementations of Perl occasionally crash. Perl threading is still not ready for production systems, at least through version 5.6. Ironically, the instability even affected scripts that don't use the threading features. For example, under high client loads the pure accept-and-fork server of Figure 15.3 would frequently hang when run under a threaded Perl interpreter. This problem disappeared when I retested the server using a version of Perl compiled without thread support. |