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

[PROC-1539] Export last CPU id used by a process #41

Open
wants to merge 1 commit into
base: dd
Choose a base branch
from

Conversation

ddyurchenko
Copy link

The use case is to check that process on host system respects cpusets (https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/cpusets.html).

For example, when running benchmarks, it is imperative for repeatability of measurements that benchmarked process is isolated and none other process uses same CPU, or even better, CPU socket.

--

Linux:

It is done by analyzing /proc//stat values. Field 39 is last processor used as per https://man7.org/linux/man-pages/man5/proc.5.html.

--

Darwin:

I use macOS Monterey 12.3.1, MacBook Pro 2020, Intel(R) Core(TM) i7-1068NG7 CPU @ 2.30GHz.

I made a research in attempt to find a reliable way to identify last CPU id used by a process.
However, it seems that MacOS doesn't provide necessary knobs by design.

(1) As per https://developer.apple.com/library/archive/releasenotes/Performance/RN-AffinityAPI/

OS X does not export interfaces that identify processors or control thread placement

Neither top and ps utilities report last CPU id for processes.

However it is possible to specify CPU affinity hints for a thread as describe in API above.

(2) I found that in htop it is possible to enable PROCESSOR field, but it always displays 0.

I analyzed source code of htop (https://github.com/htop-dev/htop/tree/main/darwin) and found that instead
of spawning ps processes like gopsutil does, it relies on MacOS system calls, which is much faster and can
be potential improvement for gopsutil (works like in https://blog.guillaume-gomez.fr/articles/2021-09-06+sysinfo%3A+how+to+extract+systems%27+information).

I checked results from syscalls in detail, and found that they don't include information about last CPU id either:

https://github.com/apple/darwin-xnu/blob/main/bsd/sys/proc.h#L102
https://github.com/apple/darwin-xnu/blob/main/bsd/sys/sysctl.h#L975
https://opensource.apple.com/source/adv_cmds/adv_cmds-158/ps/ps.c

(3) The next thing I found that someone created DTrace script to report last CPU id per thread:

https://github.com/elazarl/cpu_affinity

However, it doesn't work any longer, because dtrace that is included in MacOS doesn't support sched:::on-cpu and sched::off-cpu
(see https://docs.oracle.com/cd/E19253-01/817-6223/chp-sched-5/index.html for info on probes). When I run sudo dtrace -l, it has plenty of probes, but not the above mentioned.

Dtrace in MacOS is quite limited, and apparently situation since http:https://dtrace.org/blogs/ahl/2008/01/18/mac-os-x-and-the-missing-probes/ didn't improve.

(4) I found that you can call sudo cpuwalk.d 1 (DTrace utility shipped with MacOS - source code is available on https://opensource.apple.com/source/dtrace/dtrace-147.20.2/DTTk/Cpu/cpuwalk.d.auto.html) to get CPU assignments for each process.

It works, but integrating it into gopsutil will require quite some hacking, which I simply don't have time to do now.

--

Windows:

It is possible to specify CPU affinity hints for a thread via SetThreadIdealProcessorEx() call (https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreadidealprocessorex).

Same story as with Darwin. None of default tools display which CPU was used for running the process.

According to https://superuser.com/questions/867127/determine-which-cpu-a-process-is-running-on?lq=1, the requested feature is not directly available on Windows.

However there is also mention that it is possible to get used CPU ids from xperf traces. I am not sure though if the overhead is worth it.

There is also API call GetCurrentProcessorNumber() that returns the processor for the current thread, but it is callable only from inside the thread itself:
https://docs.microsoft.com/en-gb/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentprocessornumber?redirectedfrom=MSDN

I tried Microsoft pstools (https://docs.microsoft.com/en-gb/sysinternals/downloads/pstools), but though they provide a lot of interesting information, they don't report CPU id either.

Thus no implementation so far.

The use case is to check that process on host system respects cpusets (https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/cpusets.html).
For example, when running benchmarks, it is imperative for repeatability of measurements that benchmarked process is isolated and none other process
uses same CPU, or even better, CPU socket.

--

**Linux:**

It can be done by analyzing /proc/<pid>/stat values. Field 39 is last processor used as per https://man7.org/linux/man-pages/man5/proc.5.html.

--

**Darwin:**

I use macOS Monterey 12.3.1, MacBook Pro 2020, Intel(R) Core(TM) i7-1068NG7 CPU @ 2.30GHz.

I made a research in attempt to find a reliable way to identify last CPU id used by a process.
However, it seems that MacOS doesn't provide necessary knobs by design.

(1) As per https://developer.apple.com/library/archive/releasenotes/Performance/RN-AffinityAPI/

> OS X does not export interfaces that identify processors or control thread placement

Neither top and ps utilities report last CPU id for processes.

However it is possible to specify CPU affinity hints for a thread as describe in API above.

(2) I found that in htop it is possible to enable PROCESSOR field, but it always displays 0.

I analyzed source code of htop (https://github.com/htop-dev/htop/tree/main/darwin) and found that instead
of spawning `ps` processes like gopsutil does, it relies on MacOS system calls, which is **much faster** and can
be potential improvement for gopsutil (works like in https://blog.guillaume-gomez.fr/articles/2021-09-06+sysinfo%3A+how+to+extract+systems%27+information).

I checked results from syscalls in detail, and found that they don't include information about last CPU id either:

https://github.com/apple/darwin-xnu/blob/main/bsd/sys/proc.h#L102
https://github.com/apple/darwin-xnu/blob/main/bsd/sys/sysctl.h#L975
https://opensource.apple.com/source/adv_cmds/adv_cmds-158/ps/ps.c

(3) The next thing I found that someone created DTrace script to report last CPU id per thread:

https://github.com/elazarl/cpu_affinity

However, it doesn't work any longer, because dtrace that is included in MacOS doesn't support `sched:::on-cpu` and `sched::off-cpu`
(see https://docs.oracle.com/cd/E19253-01/817-6223/chp-sched-5/index.html for info on probes). When I run `sudo dtrace -l`, it has plenty of probes, but not the above mentioned.

Dtrace in MacOS is quite limited, and apparently situation since http:https://dtrace.org/blogs/ahl/2008/01/18/mac-os-x-and-the-missing-probes/ didn't improve.

(4) I found that you can call `sudo cpuwalk.d 1` (DTrace utility shipped with MacOS - source code is available on https://opensource.apple.com/source/dtrace/dtrace-147.20.2/DTTk/Cpu/cpuwalk.d.auto.html) to get CPU assignments for each process.

It works, but integrating it into gopsutil will require quite some hacking, which I simply don't have time to do now.

--

**Windows:**

Same story as with Darwin. None of default tools display which CPU was used for running the process.

It is possible to specify CPU affinity hints for a thread via `SetThreadIdealProcessorEx()` call (https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreadidealprocessorex).

There is also API call GetCurrentProcessorNumber() that returns the processor for the current thread, but it is callable only from inside the thread itself:
https://docs.microsoft.com/en-gb/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentprocessornumber?redirectedfrom=MSDN

I tried Microsoft pstools (https://docs.microsoft.com/en-gb/sysinternals/downloads/pstools), but though they provide a lot of interesting information, they don't report CPU id either.

According to https://superuser.com/questions/867127/determine-which-cpu-a-process-is-running-on?lq=1, the requested feature is not easily available on Windows.
However there is also mention that it is possible to get used CPU ids from xperf traces. I am not sure though if the overhead is worth it.
@brycekahle brycekahle added the fork-specific changes only present in fork label Jan 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fork-specific changes only present in fork
Projects
None yet
2 participants