RoboProg's / Software Development
Really? Better [1] in what situation?
Perl is the fastest! No, Java is the fastest! What I really meant to say is, C is the fastest! Would you believe that all of these answers are correct, under the right circumstances? Of course you would. (but which circumstances?)
A while back, I put together a test to compare forking and threading, using several implementations. I recently expanded my choice of languages a bit, as well as adding an option to run the entire task set sequentially, just to get an idea how each language would handle a batch. Keep in mind that the bulk of the "work" done by these demo programming examples is creating / updating / discarding strings, just like most real business applications, rather than calculating fibonacci sequences, prime number generation, supernova simulations, or tracking the path of a projectile from the BFG.
So, here are the scenarios I considered, as well as the language [2] that did the best in each category.
I have summarized the results below
Host | Implementation | Method | Elapsed Time (sec) |
Relative Speed (Perl + Sequential = 1, 0 = instant) |
---|---|---|---|---|
Atom | C | Sequential | 0.34 | 1.06 |
Atom | C | Fork | 9.96 | 31.1 |
Atom | C | Thread [3] | N/A | |
Atom | Perl | Sequential | 0.32 | 1 |
Atom | Perl | Fork | 36.45 | 114 |
Atom | Perl | Thread [4] | 57.88 | 181 |
Atom | Java | Sequential | 1.04 | 3.25 |
Atom | Java | Fork [5] | N/A | |
Atom | Java | Thread | 1.30 | 4.06 |
Atom | Python | Sequential | 0.73 | 2.28 |
Atom | Python | Fork | 52.79 | 165 |
Atom | Python | Thread | 7.80 | 24.4 |
Atom | Ruby | Sequential | 0.82 | 2.56 |
Atom | Ruby | Fork | 23.46 | 73.3 |
Atom | Ruby | Thread [4] | 2.39 | 7.47 |
Pentium D | C | Sequential | 0.16 | 1.23 |
Pentium D | C | Fork | 3.66 | 28.2 |
Pentium D | C | Thread [3] | N/A | |
Pentium D | Perl | Sequential | 0.13 | 1 |
Pentium D | Perl | Fork | 66.50 | 512 |
Pentium D | Perl | Thread [4] | 106.05 | 816 |
Pentium D | Java | Sequential | 3.29 | 25.3 |
Pentium D | Java | Fork [5] | N/A | |
Pentium D | Java | Thread | 3.87 | 29.8 |
Pentium D | Python | Sequential | 0.98 | 7.54 |
Pentium D | Python | Fork | 136.34 | 1049 |
Pentium D | Python | Thread | 40.17 | 309 |
Pentium D | Ruby | Sequential | 0.45 | 3.46 |
Pentium D | Ruby | Fork | 33.56 | 258 |
Pentium D | Ruby | Thread [4] | 4.13 | 31.8 |
Each task was run 10,001 times [6], using the method (sequential; fork; thread) inticated. The median time of 5 trials is the time reported above.
Further details: The Atom is a "slow processor, fast memory bus" combination (1600 MHz CPU, 512 KB cache with 1024 MB of 533 MHz memory); while the Pentium-D is a "fast processor, slow memory bus" combination (3000 MHz CPU, 1024 KB cache with 1024 MB of 300 - 400 MHz memory -- I lost the papers on the RAM, so I am not completely sure of its unannounced speed). Also, I seem to have managed to burden each machine with additional crud since last spring, so they are now running a little slower. For the Atom, most of the slow down might be due to enabling the hyper-threading. For the Pentium-D, the change must be due to additional server bloat I've gratuitously installed. Nevertheless, these are the level, but bumpy, playing fields I have provided for each implementation.
Please feel free to download the source (and my logs) and see how these work on your system(s). I would like to know if there are any unexpected results on any much slower or faster systems.
Some parting thoughts: Generating a bunch of tasks, via fork or new threads, turns out to be a really bad way to handle incoming requests on a server. A better way [7] is to have a front end process which inserts commands/requests into a queue, which is itself dequeued by a small number of worker tasks, and another queue which communicates results back from the workers to the front end, or some variation on this theme. But that is not the subject matter for today's rant.
Notes:
Contact me: |
r |
o |
b |
o |
p |
r |
o |
g |
@ |
yahoo.com |