Skip to content
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

Black Freezes in Containers on Nodes with a Large os.cpu_count() #2513

Closed
FHTMitchell opened this issue Sep 27, 2021 · 6 comments · Fixed by #2514
Closed

Black Freezes in Containers on Nodes with a Large os.cpu_count() #2513

FHTMitchell opened this issue Sep 27, 2021 · 6 comments · Fixed by #2514
Labels
T: bug Something isn't working

Comments

@FHTMitchell
Copy link
Contributor

FHTMitchell commented Sep 27, 2021

Describe the bug

Black attempts to run with too many executed threads when running in a container (e.g. in kubernetes).

It is well understood that containers do not mask the number of physical cores available, despite the fact that the container itself might be limited by the amount of CPU it can use at one time. This means that using the result of os.cpu_count() to spin up that many threads can cause a huge number of threads to be created. The memory overhead of this can cause the program to freeze or crash. See how this has impacted other projects:

We use black in our CI (via precommit) stack which runs on Kubernetes and are currently unable to run any builds using black (and so have had to turn it off for now).

To Reproduce

  1. Simply log into your nearest 1000 core machine
  2. Start a container on the machine with reasonable resource limits (e.g. 2 CPU & 1GB RAM)
  3. Run black file1.py file2.py (must be more than 1 file)
  4. Watch as black grinds to a halt trying to start 1000 threads

Expected behavior

Black does not grind to a halt...

Environment:

  • Version: 21.9b0
  • OS and Python version: Linux/[3.7|3.8|3.9]

Does this bug also happen on main?

Yes, you can see the offending code on HEAD here.

Resolution

I would suggest the easiest solution would be to add a --workers argument to black to optionally set the number of threads. I have a PR ready to go.

@FHTMitchell FHTMitchell added the T: bug Something isn't working label Sep 27, 2021
@cooperlees
Copy link
Collaborator

cooperlees commented Sep 27, 2021

We try to limit the number of CLI switches. Are there generic APIs black could possibly query to:

  • Workout if we're in a container
    • If so, maybe generate to 1 vCPU?
  • Workout how many CPUs a container has?

that work in the majority of Linux containers?

Just asking and playing devils advocate here to see if we could do saner auto detection rather than add yet another a CLI switch (and I'm not ruling it out just wondering here).

FHTMitchell added a commit to FHTMitchell/black that referenced this issue Sep 27, 2021
@FHTMitchell
Copy link
Contributor Author

FHTMitchell commented Sep 27, 2021

Thank you for the quick reply @cooperlees.

We did talk about that here, and the issues I mentioned above have looked into it.

  • One option is using len(os.sched_getaffinity(0)). This is the available CPUs but that requires that you set the cgroup on your container, which isn't yet supported by many container managers. I know our version of K8s doesn't yet.
  • Another would be simply setting the maximum to be some reasonable number. This is what we do in win32 here. Do people really need to run on more that 32 (or even 16 or 8!) threads?
  • Figuring out if we are in containers is not as simple as it sounds. There are ways for docker/k8s but this wouldn't be generic. Other container types would be ignored. A generic solution for how many CPUs a container is limited to is more or less impossible.

I'll submit my PR but happy for it to be rejected if a better solution is found. I'd rather get this solved sooner than later though, a lot of projects are currently blackless where I work :(

I understand why black attempts to reduce the number of CLI switches, and I support it, but I think this is a genuine use case, changing how the program runs rather than what it does.

@felix-hilden
Copy link
Collaborator

I think our opposition to new configuration values is more important in the context of formatting preferences, not as much in this case. But I think setting a maximum would also be fine! 8-16 seems reasonable, although I couldn't argue why not 32 or more.

@FHTMitchell
Copy link
Contributor Author

Yeah I'd obviously be happy with just limiting the number of threads. It's up to you lot if you're worried about breaking people's workflow or not. Also happy to implement that PR.

@JelleZijlstra
Copy link
Collaborator

I think it's fine to add a new --workers flag. As Felix said, a new flag affecting how Black schedules formatting is not nearly as bad as one that affects the output.

@felix-hilden
Copy link
Collaborator

My money's on the flag too, because then we don't have to set an arbitrary limit to how much Black can be scaled for potentially huge workloads. Not that it's very likely to be an issue for more than 10 people in the world, but anyways.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T: bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants