in reply to multi thread problem in an simple HTTP server
I corrected it early on and then forgot about it.
This is what you would have seen had you had warnings enabled:
Argument "HTTP::Date" isn't numeric in gmtime at C:/Perl64/lib/HTTP/Da +te.pm line 26
The line in your code that causes this error is:
$res->push_header( 'Expires' => HTTP::Date->time2str( $stat{'data'}{'e +ph'}{'expi'} ) );
You are calling time2str as class method when it is expecting to be called as a function:
$res->push_header( 'Expires' => HTTP::Date::time2str( $stat{'data'}{'e +ph'}{'expi'} ) );
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: multi thread problem in an simple HTTP server
by bravesoul (Initiate) on Apr 13, 2009 at 03:46 UTC | |
| [reply] |
|
Re^2: multi thread problem in an simple HTTP server (refactoring)
by bravesoul (Initiate) on Apr 14, 2009 at 14:32 UTC | |
At last I decide to switch to Cywin environment, because it can work perfectly there. I will continue to fix bug, apply suggestion, and add new features. Here is the updated version, any suggestion will be appriciated, thanks in advance.
| [reply] [d/l] |
by BrowserUk (Patriarch) on Apr 15, 2009 at 04:27 UTC | |
At last I decide to switch to Cywin environment, because it can work perfectly there. Hm. Why you think you need to "switch to Cygwin environment" is beyond me. You code as posted run (*)Example 1: You've ignored my suggestion to use Thread::Queue::dequeue_nb() and substituted your 'beat' messages to try and ensure that your MAIN_LOOP wakes up in a timely fashion. But your beat message will only get sent each time one of your threads either accepts and in-bound connection; or its accept() times out! With your timeout set to 10 seconds, nothing will happen in your MAIN_LOOP for up to 10 seconds unless you are receiving connections. If you had substituted dequeue_nb() and a short sleep in the MAIN _LOOP, it would have remained as responsive as you chose--every 1 second or 1/10th second, regardless of your accept timeout or traffic load. But the real kicker is--as I identified earlier--your queue serves no purpose! Every action taken as a result of one of your notify() messages is to adjust values in thread specific shared variables. So, why send a message from your worker threads to your main thread to adjust those values, when those workers have direct access to those shared variables? All you are doing is delay those actions through several layers of unnecessary locking--those associated with the queue itself, and those that prevent your main thread from accessing the thread specific shared data. If each thread adjusted its own state variables--neither type of locking wold be required! (*)Example 2: In your do_miner(), you have this notify:
which sends a message to your MAIN_LOOP that invokes this code:
But why have your miner thread send a message (via a queue with all the context switching and locking that involves), in order to set two shared variables (involving further locking), when that thread already has direct access to those two thread specific, shared variables? Both those lumps of code can be trivially reduced to:
Removing two layers of locking and context switches. You may say that it only happens every 600 seconds, but why have a thread wake up every 600 seconds to send a message to the main loop asking it to break of fromdoing the other things it is charged with--when that thread can do those things itself? In addition, by having both your miner thread and all your worker threads take care of maintaining their own stated, the reason for the queue disappears entirely. That leaves your MAIN_LOOP just one job to do: monitor the worker thread states and ramp their numbers up or down as required. Something that currently only gets done if the queue is empty:
Which it never will be at the times when it is most needed--when you are getting lots of inbound accepts--because your workers are tying the main loop up with pointless requests to have the MAIN_LOOP maintain their state. Here is the updated version, any suggestion will be appriciated, As you've ignored just about all the suggestions I already made, there seems little point in repeating them. However, as I've tested my 'no notify - no queue' theories, and found that even with 80 clients pounding away flat out, it can handle them perfectly whilst remaining responsive to both new clients and keyboard (sig int) under Vista and XP, whereas your version starts timing clients out after 60 seconds with only 15 clients trying to access it, you might as well have the modified code: Read more... (10 kB)
BTW: A far better use of a queue in your server would be to queue all your trc() messages to a single thread for output rather than slowing all your workers down waiting for access to a global lock. But I left that as an exercise for the reader. 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.
| [reply] [d/l] [select] |
by bravesoul (Initiate) on Apr 15, 2009 at 09:19 UTC | |
Thanks for your help. By the way, how can you achieved a "Read more... (9 kB)" linkage, it is really great! I am afraid I have no choice but pull the big block of code here.
| [reply] [d/l] |