You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fix Linux memory and CPU metrics derived from procfs (#46)
### Motivation
This package provides some system metrics on Linux derived from procfs.
These include CPU and memory metrics. The values returned from
`/proc/self/stat` need to be combined with system values. For example,
some values are returned in clock ticks or memory pages, so need to be
divided appropriately according to the system configuration for clock
ticks per second or page size, respectively.
Looking at the code, some attempt was made to do this: `_SC_CLK_TCK` and
`_SC_PAGESIZE` were used as divisors.
However, these values are the values of the _option_ parameter used in
the call to `sysconf(3)`, not the results themselves.
To illustrate this, here's a Swift program that prints the option name,
option value, and the result of `sysconf(optionValue)`:
```swift
#if !os(Linux)
import Foundation
print("error: This tool is only supported on Linux")
exit(1)
#else
import Glibc
for (optionName, optionValue) in [
("_SC_ARG_MAX", _SC_ARG_MAX),
("_SC_CHILD_MAX", _SC_CHILD_MAX),
("_SC_CLK_TCK", _SC_CLK_TCK),
("_SC_NGROUPS_MAX", _SC_NGROUPS_MAX),
("_SC_OPEN_MAX", _SC_OPEN_MAX),
("_SC_STREAM_MAX", _SC_STREAM_MAX),
("_SC_TZNAME_MAX", _SC_TZNAME_MAX),
("_SC_JOB_CONTROL", _SC_JOB_CONTROL),
("_SC_SAVED_IDS", _SC_SAVED_IDS),
("_SC_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS),
("_SC_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING),
("_SC_TIMERS", _SC_TIMERS),
("_SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO),
("_SC_PRIORITIZED_IO", _SC_PRIORITIZED_IO),
("_SC_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO),
("_SC_FSYNC", _SC_FSYNC),
("_SC_MAPPED_FILES", _SC_MAPPED_FILES),
("_SC_MEMLOCK", _SC_MEMLOCK),
("_SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE),
("_SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION),
("_SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING),
("_SC_SEMAPHORES", _SC_SEMAPHORES),
("_SC_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS),
("_SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX),
("_SC_AIO_MAX", _SC_AIO_MAX),
("_SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX),
("_SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX),
("_SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX),
("_SC_MQ_PRIO_MAX", _SC_MQ_PRIO_MAX),
("_SC_VERSION", _SC_VERSION),
("_SC_PAGESIZE", _SC_PAGESIZE),
("_SC_RTSIG_MAX", _SC_RTSIG_MAX),
] {
let actualValue = sysconf(Int32(optionValue))
print("Option name: \(optionName), Option value: \(optionValue), Actual value: \(actualValue)")
}
#endif
```
```console
% swift sysconf-test/sysconf-test.swift
Option name: _SC_ARG_MAX, Option value: 0, Actual value: 2097152
Option name: _SC_CHILD_MAX, Option value: 1, Actual value: 63907
Option name: _SC_CLK_TCK, Option value: 2, Actual value: 100
Option name: _SC_NGROUPS_MAX, Option value: 3, Actual value: 65536
Option name: _SC_OPEN_MAX, Option value: 4, Actual value: 65536
Option name: _SC_STREAM_MAX, Option value: 5, Actual value: 16
Option name: _SC_TZNAME_MAX, Option value: 6, Actual value: -1
Option name: _SC_JOB_CONTROL, Option value: 7, Actual value: 1
Option name: _SC_SAVED_IDS, Option value: 8, Actual value: 1
Option name: _SC_REALTIME_SIGNALS, Option value: 9, Actual value: 200809
Option name: _SC_PRIORITY_SCHEDULING, Option value: 10, Actual value: 200809
Option name: _SC_TIMERS, Option value: 11, Actual value: 200809
Option name: _SC_ASYNCHRONOUS_IO, Option value: 12, Actual value: 200809
Option name: _SC_PRIORITIZED_IO, Option value: 13, Actual value: 200809
Option name: _SC_SYNCHRONIZED_IO, Option value: 14, Actual value: 200809
Option name: _SC_FSYNC, Option value: 15, Actual value: 200809
Option name: _SC_MAPPED_FILES, Option value: 16, Actual value: 200809
Option name: _SC_MEMLOCK, Option value: 17, Actual value: 200809
Option name: _SC_MEMLOCK_RANGE, Option value: 18, Actual value: 200809
Option name: _SC_MEMORY_PROTECTION, Option value: 19, Actual value: 200809
Option name: _SC_MESSAGE_PASSING, Option value: 20, Actual value: 200809
Option name: _SC_SEMAPHORES, Option value: 21, Actual value: 200809
Option name: _SC_SHARED_MEMORY_OBJECTS, Option value: 22, Actual value: 200809
Option name: _SC_AIO_LISTIO_MAX, Option value: 23, Actual value: -1
Option name: _SC_AIO_MAX, Option value: 24, Actual value: -1
Option name: _SC_AIO_PRIO_DELTA_MAX, Option value: 25, Actual value: 20
Option name: _SC_DELAYTIMER_MAX, Option value: 26, Actual value: 2147483647
Option name: _SC_MQ_OPEN_MAX, Option value: 27, Actual value: -1
Option name: _SC_MQ_PRIO_MAX, Option value: 28, Actual value: 32768
Option name: _SC_VERSION, Option value: 29, Actual value: 200809
Option name: _SC_PAGESIZE, Option value: 30, Actual value: 4096
Option name: _SC_RTSIG_MAX, Option value: 31, Actual value: 32
```
The results for our metrics were off because we were always using 30 for
page size and 2 for clock ticks.
### Modifications
- Remove the LinuxMain.swift: test discovery is supported on Linux for
all currently supported Swift versions.
- Update the internal documentation regarding the use of
`proc_pid_stat(5)`.
- Use correct value for CPU metrics, obtained from
`sysconf(_SC_CLK_TCK)`, not just `_SC_CLK_TCK`.
- Use correct value for memory metrics, obtained from
`sysconf(_SC_PAGESIZE)`, not just `_SC_PAGESIZE`.
- Write tests for both CPU seconds and RSS memory.
### Result
Fixes#40.
0 commit comments