Skip to content

Add Crystal::System.effective_cpu_count#16148

Merged
straight-shoota merged 9 commits intocrystal-lang:masterfrom
ysbaddaden:feature/crystal-system-effective-cpu-count
Sep 13, 2025
Merged

Add Crystal::System.effective_cpu_count#16148
straight-shoota merged 9 commits intocrystal-lang:masterfrom
ysbaddaden:feature/crystal-system-effective-cpu-count

Conversation

@ysbaddaden
Copy link
Collaborator

@ysbaddaden ysbaddaden commented Sep 9, 2025

The method is meant to return how many logical CPUs are actually available to the process versus the total number of CPUs from System.cpu_count.

  • Linux: uses sched_getaffinity syscall
  • Darwin / DragonflyBSD: unsupported
  • FreeBSD: uses cpuset_getaffinity
  • NetBSD / OpenBSD: uses sysctl(CTL_HW, HW_NCPUONLINE
  • Solaris: unknown
  • Windows: uses GetProcessAffinityMask

Refactors to have a single src/crystal/system/unix/cpucount.cr file. There's little point to differentiate BSD from the rest of UNIX for a few lines of code, and it made no sense to put a new linux method on the sysconf file or to create yet-another specific file for one single method. I added yet-another-file 🤷

The method is meant to return how many logical CPUs are actually
available to the process versus the total number of CPUs from
System.cpu_count.

Uses the linux specific `sched_getaffinity` syscall.
@straight-shoota
Copy link
Member

straight-shoota commented Sep 9, 2025

Regarding API design, I think the most relevant information is how many cores are effectively available to the current process. That should be the most straightforward method.
Ideally, I'd like cpu_count to return the effective count with a fallback to total count on systems where there's no difference. And then we could have separate methods total_cpu_count and effective_cpu_count on top of that. Not sure if the latter is relevant, though.
That would change the semantics of cpu_count a little bit, but it might be just fine.

I personally prefer different files very much. It might be debatable when there's more shared code, but here it's completely distinct code for different OSes.

And we should add a spec for the new API method(s). At least make sure that it generally works.

@HertzDevil
Copy link
Contributor

Win32:

# winbase.h
lib LibC
  alias DWORD_PTR = ULONG_PTR

  fun GetProcessAffinityMask(hProcess : HANDLE, lpProcessAffinityMask : DWORD_PTR*, lpSystemAffinityMask : DWORD_PTR*) : BOOL
end

if LibC.GetProcessAffinityMask(LibC.GetCurrentProcess, out process_affinity, out _) == 0
  raise RuntimeError.from_winerror("GetProcessAffinityMask")
end
process_affinity.popcount

This works as long as the process does not opt in to using multiple processor groups, which is relevant when there are more than 64 logical processors present: https://learn.microsoft.com/en-us/windows/win32/procthread/processor-groups

@ysbaddaden
Copy link
Collaborator Author

@HertzDevil thank you 🙇

@straight-shoota But the split files don't tell which target use what (which sysconf? which sysctl?) and it becomes awkward to know where to put the linux implementation for the effective cpu count.

@straight-shoota
Copy link
Member

Yes, the current file names are not great.
We should be fine with three files cpu_count_unix.cr, cpu_count_linux.cr, cpu_count_bsd.cr.

ysbaddaden and others added 2 commits September 9, 2025 18:34
Co-Authored-By: Quinton Miller <nicetas.c@gmail.com>
@ysbaddaden ysbaddaden changed the title Add Crystal::System.effective_cpu_count (linux) Add Crystal::System.effective_cpu_count (linux, win32) Sep 9, 2025
@ysbaddaden ysbaddaden changed the title Add Crystal::System.effective_cpu_count (linux, win32) Add Crystal::System.effective_cpu_count (linux, Sep 11, 2025
@ysbaddaden ysbaddaden changed the title Add Crystal::System.effective_cpu_count (linux, Add Crystal::System.effective_cpu_count Sep 11, 2025
@ysbaddaden
Copy link
Collaborator Author

Now with the implementation for all the targets that support it.

ysbaddaden added a commit to ysbaddaden/crystal that referenced this pull request Sep 11, 2025
@straight-shoota straight-shoota added this to the 1.18.0 milestone Sep 12, 2025
@straight-shoota straight-shoota merged commit f2342c2 into crystal-lang:master Sep 13, 2025
39 checks passed
@github-project-automation github-project-automation bot moved this from Review to Done in Multi-threading Sep 13, 2025
@ysbaddaden ysbaddaden deleted the feature/crystal-system-effective-cpu-count branch September 14, 2025 07:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

4 participants