process.GetInfoForPid collects the total thread count#96
Conversation
💔 Build Failed
Expand to view the summary
Build stats
Steps errors
Expand to view the steps failures
|
26b107e to
3b97f2f
Compare
8924cb8 to
7de1ac7
Compare
process.GetInfoForPid
process.GetInfoForPidprocess.GetInfoForPid collects the total thread count
fc1b925 to
ef72b6f
Compare
b298151 to
c3fa121
Compare
| // Windows Process Snapshotting docs: | ||
| // - https://learn.microsoft.com/en-us/previous-versions/windows/desktop/proc_snap/overview-of-process-snapshotting | ||
| // PssCaptureSnapshot docs in https://learn.microsoft.com/en-us/windows/win32/api/processsnapshot/nf-processsnapshot-psscapturesnapshot | ||
| // PssQuerySnapshot docs in https://learn.microsoft.com/en-us/windows/win32/api/processsnapshot/nf-processsnapshot-pssquerysnapshot | ||
|
|
||
| // Use golang.org/x/sys/windows/mkwinsyscall instead of adriansr/mksyscall | ||
| // below once https://github.com/golang/go/issues/42373 is fixed. | ||
| //go:generate go get github.com/adriansr/mkwinsyscall | ||
| //go:generate $GOPATH/bin/mkwinsyscall.exe -systemdll -output zsyscall_windows.go syscall_windows.go | ||
|
|
||
| //sys PssCaptureSnapshot(processHandle syscall.Handle, captureFlags PSSCaptureFlags, threadContextFlags uint32, snapshotHandle *syscall.Handle) (err error) [failretval!=0] = kernel32.PssCaptureSnapshot | ||
| //sys PssQuerySnapshot(snapshotHandle syscall.Handle, informationClass uint32, buffer *PssThreadInformation, bufferLength uint32) (err error) [failretval!=0] = kernel32.PssQuerySnapshot |
There was a problem hiding this comment.
If anyone has a suggestion on how to better organise it, I'd appreciate. I don't quite like how it's now, but also I'm not sure which other organisation could be better.
| assert.Equal(t, want, got) | ||
| } | ||
|
|
||
| func TestParsePIDInfos(t *testing.T) { |
There was a problem hiding this comment.
I don't fully get the name of this test. If I understood it correctly, it's testing parseProcStat, however it is called ParsePIDInfos.
| func TestParsePIDInfos(t *testing.T) { | |
| func TestParseProcStat(t *testing.T) { |
c3fa121 to
c0d90b9
Compare
|
|
||
| // TestFetchNumThreads only checks some value is returned for NumThreads. However, | ||
| // it cannot verify the correctness of the value. | ||
| func TestFetchNumThreads(t *testing.T) { |
There was a problem hiding this comment.
You could test this by writing a program that runs a known number of threads. The trick is that it can't be a Go program to get control over it. A simple C program with a main function that just sleeps until it is terminated is guaranteed to be only one thread, or you could spawn a known number of threads directly with the pthreads API, or you could write it in C++ and use with std:thread which is probably easier to do.
Hardest part would be getting CI to compile the program but this repository already depends on CGO so there must be a C compiler available already.
There was a problem hiding this comment.
This would also work for Linux, and if you used std:thread in C++ it would also work for Windows without writing a separate test program. As mentioned, the biggest hurdle will be ensuring you have a C++ toolchain available with the appropriate version of C++ available for std:thread support but I hope this is already the case.
| @@ -0,0 +1,168 @@ | |||
| // from https://github.com/zodiacon/Win10SysProgBookSamples/blob/56883f5126f5e29a03d01896f87ce7b82f51fa10/Chapter20/snapproc/snapproc.cpp | |||
There was a problem hiding this comment.
What is the license of this code? Are you allowed to copy it here?
It seems like you might be better off with just linking to the book with instructions on how to build it unless you've modified this significantly.
belimawr
left a comment
There was a problem hiding this comment.
All good from my side, but I like Craig's idea to have a simple C++ program spawning a known number of threads for testing.
c9b166f to
a913cc8
Compare
|
The images used for CI are defined in elastic-agent-system-metrics/.buildkite/pipeline.yml Lines 6 to 7 in dc997bd For Linux at least the Go image contains a pre-installed version of g++ you could use. I have no idea what is in that Windows container, but you could modify the powershell script that runs the tests to find out by trying to invoke a few of the toolchains you expect might exist. elastic-agent-system-metrics/.buildkite/scripts/run-win-tests.ps1 Lines 10 to 18 in dc997bd We have a dependency manager called chocolately, it's possible you could use it to install mingw. As for actually compiling the binaries it might be easier to do it with an explicit mage target like Even if you can't get it to work in CI you can document the commands used to build the executables in mage and just not invoke them in CI (although I hope doing it for Linux at least won't be that bad). |
954635a to
afd1b55
Compare
* On linux: - it extends the information parsed from /proc/[PID]/stat to get the total thread count - unit tests added, they mock /proc/[PID]/stat * On darwin: - it uses the syscall proc_pidinfo - unit test only validates GetInfoForPid does not return an error and the total thread count ins't zero * On windows: - it uses the Process Snapshotting APIs: https://learn.microsoft.com/en-us/previous-versions/windows/desktop/proc_snap/overview-of-process-snapshotting - unit test only validates GetInfoForPid does not return an error and the total thread count ins't * Add a unit test using a C++ program which runs exactly 42 threads so we can assert the data read by process.GetInfoForPid On windows the and newer the process start with more threads than the program requests to parallel load needed tabels/dll or some windows specific things. Therefore the test on windows accepts 42 or 45 for the number of threads allocated to the process. See the following for details https://stackoverflow.com/questions/42789199/why-there-are-three-unexpected-worker-threads-when-a-win32-console-application-s/42789684#42789684
878ae11 to
2f28d53
Compare
| // is launching. It seems to be due to it loading dll/tables in parallel | ||
| // or de default thread pool. See the following for more info: | ||
| // https://stackoverflow.com/questions/42789199/why-there-are-three-unexpected-worker-threads-when-a-win32-console-application-s/42789684#42789684 | ||
| expected := 45 |
There was a problem hiding this comment.
Can you ensure it's always 45 threads?
One option is to run the program for a while and use the eventually assertion to wait for when the number of threads goes back to 42
There was a problem hiding this comment.
it takes around 30s on my machine to have the number go back to 42. As it's been pretty deterministic, on my machine and on CI, I'm doing this double test. It accounts exactly for the extra threads, if something changes in the future the test sill fails and there should be enough explanation in the test for anyone else o understand the problem and fix it
What does this PR do?
Collect the total thread count, num_threads, as part of the information collected by
process.GetInfoForPidWhy is it important?
To enable metricbeat to collect the total thread count per process as requested by elastic/beats#34461.
Checklist
CHANGELOG.mdRelated issues