|Just another Perl shrine|
Re^5: How to maintain a persistent connection over sockets? (Amazing! Multi-tasking without multi-tasking!)by BrowserUk (Pope)
|on May 05, 2012 at 05:43 UTC||Need Help??|
That code is remarkable! Also, unfortunately badly wrong, but I'll get back to that.
You have succeeded in writing a multi-tasking server without using any form of multi-tasking. Neither threading, nor forks, nor polling; nor an event loop!
It is utterly, utterly amazing. It took me quite a while to understand just how it achieved that. I now understand your thread title!
It is even more amazing that it achieves the throughput that it does; but is unsurprising that it is not meeting with your expectations.
Your server is resolutely single tasking. And it is also quite difficult to explain how it manages to give the appearance (and indeed, the actions) of being multi-tasking, in terms of the code alone, so I'm going to resort to an analogy.
How can you conduct two (or more) 'concurrent' conversations using one phone that has neither call-waiting; nor conferencing facilities?
The solution is to ask the other parties to disconnect and redial after each snippet of conversation. One person rings, you say "Hello"; they hang up and redial; when you pick up they reply; then hang up and re-dial; this time when you pick up, you reply; and they hang-up and redial; and so on until the conversation is complete.
And if two or more people follow this procedure, then you will be able to hold 'simultaneous' conversations with all of them. They'll just be very slow and disjointed conversations.
That is exactly analogous to how your server is "working".
I am truly surprised at how you arrived at this solution; and totally amazed at how efficiently it actually works. I guess it personifies the old adage about computers being able to do everything very, very quickly; including the wrong thing :)
Of course, it is unsustainable for an application such as yours. You will need to use some form of multi-tasking.
This comes in (essentially) 4 forms with the following traits:
My preferred solution for your application would be a combination of two of the four. Specifically, I would run a single phone&receptionist (a select loop) within a thread. That select loop would take care of all the communications with the clients, but would hand off queries to a pool of agents (work threads).
That allows the receptionist to respond immediately to new callers and inbound queries and modification requests from existing clients; whilst the pool of agents (work threads) take care of the doing the actual work. The pool can be tailored (scaled) to fit the available hardware (number of cores; amount of memory), on a case by case basis; whilst being able to both reference and make modifications to the shared data.
IMO, this will deliver the best combinations of responsiveness and functionality for your scenario.
Give me a few days and I'll get back to you with demonstrations of the 3 main candidates plus my preferred hybrid solution.
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.