Re: [dancer-users] single-threaded
On Tue, Nov 24, 2015 at 7:00 AM, <dancer-users-request@dancer.pm> wrote:
This means that if you write your Dancer route handlers to be efficient, so that they return within a few milliseconds at most, you can in effect serve a great many clients, since most of them will be idle most of the time.
The single-threaded web server only breaks down when you start getting to load levels where the server is handling at least one connection all the time, so that allowing to to handle a second or third in parallel can provide some benefit.
What if your route handler goes to disk for something (perhaps a DB access)? Your other Starman process(es) could start handling another connection in the meantime. What if your CPU has 2 or more cores (likely)? Again, the other process could get going. Maybe you have low traffic on an Intranet. But out on the Internet, you could have bots and spiders bothering your route handlers just when you have a real client to serve. Cheers -- Rick
On Nov 24, 2015, at 6:48 AM, Rick Leir <richard.leir@canadiana.ca> wrote:
The single-threaded web server only breaks down when you start getting to load levels where the server is handling at least one connection all the time, so that allowing to to handle a second or third in parallel can provide some benefit.
What if your route handler goes to disk for something (perhaps a DB access)? Your other Starman process(es) could start handling another connection in the meantime.
A DB access should be over in a matter of milliseconds in most apps. Let’s say your heaviest query is 50 ms. That’s short enough that you could have 200 of those per second and still do it all in a single thread.
What if your CPU has 2 or more cores (likely)? Again, the other process could get going.
I thought we were talking about I/O bound processes, not CPU-bound processes. If you take a single-threaded app that is bottlenecked on the disk, adding a second thread will just cause that first thread to spend half its time waiting on the disk, too. (The kernel will ping-pong among those threads.) If your DB is small enough to end up RAM-backed by the kernel’s buffer cache after it’s been running for a while, that will drop DB access times by a factor of 1000 or so, if most of your workload is reading, which increases the number of clients you can serve by a similar factor. Alternately, if your workload doesn’t exceed 1.0 full CPU cores consistently, you’ll chew up any speed increase you get from multicore waiting on synchronization locks, context switches, etc. Let’s also not forget that I advocated running your Dancer app behind a fully-featured proxy server such as nginx or mod_proxy, which gets you a lot of concurrency all by itself. Try this: create environments/single-threaded.yml, with the “simple" web server and session manager. Put it behind a proxy server, then run a concurrent web benchmark against it. I use Siege[*], and it just gave me a concurrency value of 36.60 on my app here. Why is it > 1.0? Because a huge number of the URLs in my app are static assets, not dynamic, so the proxy server handled those. [*] https://www.joedog.org/siege-home/
Maybe you have low traffic on an Intranet. But out on the Internet, you could have bots and spiders bothering your route handlers just when you have a real client to serve.
Going multi-threaded just means you need a bigger DDoS to take the site down. Adding cores is no way to fight off a DDoS. To do that, you need massive bandwidth, not cores. Look, I’m not saying that multi-core Dancer apps have no purpose. I’m saying that until your app starts maxing out a single core, you won’t get any benefit from making it multi-thread capable.
On Nov 24, 2015, at 12:29 PM, Warren Young <wyml@etr-usa.com> wrote:
Try this: create environments/single-threaded.yml, with the “simple" web server and session manager. Put it behind a proxy server, then run a concurrent web benchmark against it. I use Siege[*], and it just gave me a concurrency value of 36.60 on my app here.
Scratch that. I was misinterpreting what “concurrency” means in Siege reports. 36.6 doesn’t mean 36.6 simultaneous transfers, it means 36.6 conns were blocked at a time on average. High concurrency is a bad thing, not a good thing. But that test result was bogus because I was using old invalid test data. On regenerating the URL list that Siege uses to be valid for my current web app, a Siege run with 25 concurrent connections gives a concurrency < 1. That means that even though the dynamic part of the app is single-threaded, on average, clients *never* had to wait for service, even though there were 25 simultaneous conns all trying to pull data at once. The answer to “why?” is as before: because most of the URLs are handled by the reverse proxy server, not by the Perl web server underneath it. Realize that testing with 25 Siege users is equivalent to many times that many real users, since Siege runs through the URLs as fast as possible. Unlike a human, it doesn’t take time to read the generated web page, think about it, and move the mouse to the next clickable thing. I encourage you to try the same test on your app. Run it multi-threaded with a reasonable number of Siege conns, then switch it to single-threaded and retry. I should point out that my single-threaded app uses the “simple” session manager, which means sessions are held in RAM, and are accessed without locking. This is very fast, but means all sessions disappear when the Dancer app restarts. That’s fine for my app, but might not be appropriate for all.
participants (3)
-
Gabor Szabo -
Rick Leir -
Warren Young