-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Passenger creates an unnecessary amount of threads on systems with many CPUs #275
Comments
After even more digging around, we actually found that there's an option in Passenger for doing this, even though it's not particularly well documented. In Passenger's Config.h header it's documented as "read_only". However, by setting the following in the ---
# nginx_stage
passenger_options:
passenger_ctl: "controller_threads 1" On our system with 12 CPUs, we get this result after logging in:
So this issue can be closed without packaging changes. We would still like to hear if you've encountered this issue, or if we are the first to voice this concern. Since this configuration concerns the ---
# Need to use a multi-line string to inject more than one passenger_ctl option:
passenger_options:
passenger_ctl: 'hook_after_watchdog_shutdown /opt/ood/scripts/cleanup.sh;
passenger_ctl controller_threads 1' |
Hey sorry for the delay.
Yes I think you're the first to bring this up. I'm not against patching ondemand-passenger, but you seem to have found a work around. Even so, I'd like to keep the ticket open because it would seem that something needs to be done. Seems like |
Interesting. I guess others may not have put as many CPUs under OOD as we have, or they have just silently accepted this behavior, or fixed it on their own.
That's good to hear. Yes, I believe the workaround is more elegant than patching Passenger in the ondemand-packaging build step for this particular need. So let's not pursue that at this stage.
That might be a suitable solution, yes. We've verified that the multi-line string trick that I commented above results in a working configuration, but it would be more elegant to have something like: # Example configuration:
---
passenger_ctl:
- 'hook_after_watchdog_shutdown /opt/ood/scripts/cleanup.sh;'
- 'controller_threads 1' That would probably go into the |
I assume so, but I'm not sure if it'll accept multiple values for the same key. Again, having never seen |
If you're referring to adding multiple entries of I think we might need to add a separate nginx_stage configuration option for it, so that it can be added separately. E.g., this might work the way we'd like it to: <%- passenger_ctl_options.to_a.each do |value| -%>
passenger_ctl "<%= value -%>";
<%- end -%> with the inputs: ---
passenger_ctl_options:
- 'hook_after_watchdog_shutdown /opt/ood/scripts/cleanup.sh;'
- 'controller_threads 1'
passenger_options:
# separate options here ... |
In our opinion, it might be reasonable to consider overriding the At least we'd suggest documenting that OOD recommends setting this to something low, e.g., in your nginx_stage.yml documentation, if you do not want to alter the defaults. |
Passenger will spawn worker threads in each per-user-nginx (PUN) instance based on the amount of cores on the system where OOD runs. This behavior probably makes sense when running only a single web server instance. However, when OOD is launching one Nginx instance per user, and an OOD deployment has hundreds of users, there starts to be a lot of threads.
There are a few issues with having this many threads. Passenger will monitor the CPU and memory usage of all these threads by running
ps(1)
regularly, and this creates a high system load on the OOD host. We have seen load averages spike into the thousands on a regular basis, which we suspect Passenger is to blame for. Using theperf(1)
tool at the tail end of such a load spike, we could see thatPassengerAgent
is the culprit behind a lot of context switches.For context, one of our clusters runs OOD on a 12 core VM, with several hundreds of users. At the point of writing, there were 722 PUNs, 1461 PassengerAgent processes, and 26754 PassengerAgent threads.
We investigated the issue and found that Passenger will ultimately use the Boost
thread::hardware_concurrency()
function (link to source code) to decide what amount of threads to spawn for its agent.It's possible that Passenger has some knobs for tuning its parallelism, but we suspect they are under the Passenger Enterprise offering. Luckily, the Passenger source code is MIT licensed, so we are able to patch it to better suit OOD's architecture.
We were able to patch this via the ondemand-passenger rpmbuild spec, to accept an environment variable which overrides the default behavior when defined and containing a valid, positive integer. If you are interested in upstreaming this patch, we will gladly open a pull request.
With this patch, and the override set to
2
(instead of 12), we're reducing the amount of threads per PUN by 20. The benchmark we used was to restart the instance, and then log into the dashboard. Thepstree -u username
outputs are attached below:On systems with even more CPU threads available, the improvement is naturally even greater. Running OOD on a host with 256 hardware threads will result in a pstree that looks like this:
I.e., the amount of reduced threads per PUN could be 508 with this patch and override to 2 threads hardware_concurrency 🙂
Let us know what you think!
The text was updated successfully, but these errors were encountered: