pmemstat 2.3.28__tar.gz → 2.3.29__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pmemstat-2.3.29/.gitignore +5 -0
- {pmemstat-2.3.28/src/pmemstat.egg-info → pmemstat-2.3.29}/PKG-INFO +7 -8
- pmemstat-2.3.29/deploy +8 -0
- pmemstat-2.3.29/images/help-screen.png +0 -0
- pmemstat-2.3.29/images/pmemstat.png +0 -0
- pmemstat-2.3.29/images/scroll-pos.png +0 -0
- pmemstat-2.3.29/memtest.c +215 -0
- pmemstat-2.3.29/pyproject.toml +30 -0
- pmemstat-2.3.29/run.sh +9 -0
- pmemstat-2.3.28/PKG-INFO +0 -202
- pmemstat-2.3.28/pyproject.toml +0 -72
- pmemstat-2.3.28/setup.cfg +0 -4
- pmemstat-2.3.28/src/pmemstat.egg-info/SOURCES.txt +0 -14
- pmemstat-2.3.28/src/pmemstat.egg-info/dependency_links.txt +0 -1
- pmemstat-2.3.28/src/pmemstat.egg-info/entry_points.txt +0 -2
- pmemstat-2.3.28/src/pmemstat.egg-info/requires.txt +0 -1
- pmemstat-2.3.28/src/pmemstat.egg-info/top_level.txt +0 -1
- {pmemstat-2.3.28 → pmemstat-2.3.29}/LICENSE.txt +0 -0
- {pmemstat-2.3.28 → pmemstat-2.3.29}/README.md +0 -0
- {pmemstat-2.3.28/src → pmemstat-2.3.29}/pmemstat/CpuSmooth.py +0 -0
- {pmemstat-2.3.28/src → pmemstat-2.3.29}/pmemstat/KillThem.py +0 -0
- {pmemstat-2.3.28/src → pmemstat-2.3.29}/pmemstat/Window.py +0 -0
- {pmemstat-2.3.28/src → pmemstat-2.3.29}/pmemstat/__init__.py +0 -0
- {pmemstat-2.3.28/src → pmemstat-2.3.29}/pmemstat/main.py +0 -0
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: pmemstat
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.29
|
|
4
4
|
Summary: Report Proportional Memory on Linux
|
|
5
|
-
Author-email: Joe Defen <joedef@duck.com>
|
|
6
|
-
License: MIT
|
|
7
|
-
Project-URL: Homepage, https://github.com/joedefen/pmemstat
|
|
8
|
-
Project-URL: Bug Tracker, https://github.com/joedefen/pmemstat/issues
|
|
9
5
|
Keywords: proportional memory,RAM,htop,top,monitor
|
|
6
|
+
Author-email: Joe Defen <joedef@duck.com>
|
|
7
|
+
Requires-Python: >=3.8
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
10
9
|
Classifier: Programming Language :: Python :: 3
|
|
11
10
|
Classifier: License :: OSI Approved :: MIT License
|
|
12
11
|
Classifier: Operating System :: POSIX :: Linux
|
|
13
|
-
Requires-Python: >=3.8
|
|
14
|
-
Description-Content-Type: text/markdown
|
|
15
12
|
License-File: LICENSE.txt
|
|
16
13
|
Requires-Dist: psutil>5.9
|
|
14
|
+
Project-URL: Bug Tracker, https://github.com/joedefen/pmemstat/issues
|
|
15
|
+
Project-URL: Homepage, https://github.com/joedefen/pmemstat
|
|
17
16
|
|
|
18
17
|
> **Quick Start**: from the CLI
|
|
19
18
|
> * **If `python3 -V` shows v3.11 or later, install with `pipx`**:
|
pmemstat-2.3.29/deploy
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
// A test program for 'pmemstat' which grows its memory over time including:
|
|
2
|
+
// - stack
|
|
3
|
+
// - heap (TODO)
|
|
4
|
+
// - SysV shared memory
|
|
5
|
+
// - memory mapped files (TODO)
|
|
6
|
+
// Several instances of the this programs can be run, and, if so, the
|
|
7
|
+
// programs will share the SysV shared memory and the memory mapped files.
|
|
8
|
+
#include <stdio.h>
|
|
9
|
+
#include <stdlib.h>
|
|
10
|
+
#include <stdbool.h>
|
|
11
|
+
#include <string.h>
|
|
12
|
+
#include <sys/types.h>
|
|
13
|
+
#include <sys/ipc.h>
|
|
14
|
+
#include <sys/shm.h>
|
|
15
|
+
#include <sys/sem.h>
|
|
16
|
+
#include <unistd.h>
|
|
17
|
+
#include <sys/stat.h>
|
|
18
|
+
#include <fcntl.h>
|
|
19
|
+
#include <sys/mman.h>
|
|
20
|
+
|
|
21
|
+
#define CNT 128 /* how big can things get */
|
|
22
|
+
#define CHUNK_SIZE ((size_t)(10*1024)) /* make it a 10K shared memory segment */
|
|
23
|
+
#define BASE_KEY 0xffeeddcc
|
|
24
|
+
#define DIM(A) (sizeof(A)/sizeof(A[0]))
|
|
25
|
+
#define FILENAME "/tmp/memmapfile"
|
|
26
|
+
|
|
27
|
+
int rm_shmem();
|
|
28
|
+
int rm_mmap();
|
|
29
|
+
|
|
30
|
+
struct Args {
|
|
31
|
+
int sleep_sec; // delay per loop
|
|
32
|
+
int n_loops; // number of loops
|
|
33
|
+
} Args = {.sleep_sec = 10, .n_loops = CNT};
|
|
34
|
+
|
|
35
|
+
struct MyData {
|
|
36
|
+
int n_shmem; void *shmemp[CNT];
|
|
37
|
+
int n_malloc; void *mallocp[CNT];
|
|
38
|
+
int n_mmap; int mm_fd; unsigned char *mm_ptr;
|
|
39
|
+
} MyData;
|
|
40
|
+
|
|
41
|
+
int LoopCnt = 0;
|
|
42
|
+
|
|
43
|
+
int incr_sem() {
|
|
44
|
+
// returns the count of these processes (so the first can initialize)
|
|
45
|
+
int semid, val0, val1;
|
|
46
|
+
int key = BASE_KEY;
|
|
47
|
+
if ((semid = semget(key, 2, 0644 | IPC_CREAT)) == -1) {
|
|
48
|
+
perror("shmget");
|
|
49
|
+
exit(1);
|
|
50
|
+
}
|
|
51
|
+
struct sembuf sembufs[2] = {
|
|
52
|
+
{ .sem_num = 0, .sem_op = 1, .sem_flg = SEM_UNDO}
|
|
53
|
+
, { .sem_num = 1, .sem_op = 1, .sem_flg = 0}
|
|
54
|
+
};
|
|
55
|
+
semop(semid, &sembufs[0], 1);
|
|
56
|
+
val0 = semctl(semid, 0, GETVAL);
|
|
57
|
+
printf("semval=%d\n", val0);
|
|
58
|
+
|
|
59
|
+
for (bool done = false; !done; ) {
|
|
60
|
+
if (val0 == 1) {
|
|
61
|
+
rm_shmem();
|
|
62
|
+
rm_mmap();
|
|
63
|
+
semop(semid, &sembufs[1], 1);
|
|
64
|
+
done = true;
|
|
65
|
+
} else {
|
|
66
|
+
for (int loop = 0, val1 = 0; val1 != 1; loop++) {
|
|
67
|
+
val1 = semctl(semid, 1, GETVAL);
|
|
68
|
+
if (val1 >= 0) {
|
|
69
|
+
done = true;
|
|
70
|
+
break;
|
|
71
|
+
} else if (loop >= val0) {
|
|
72
|
+
printf("%d gave up on init; forcing it, loop=%d", val0, loop);
|
|
73
|
+
val0 = 1;
|
|
74
|
+
break;
|
|
75
|
+
} else {
|
|
76
|
+
sleep(1);
|
|
77
|
+
printf("%d waiting on val1==0, got %d, loop %d\n", val0, val1, loop);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return val0;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
//////////////////////////////// SHMEM
|
|
87
|
+
|
|
88
|
+
int add_shmem() {
|
|
89
|
+
int idx = MyData.n_shmem;
|
|
90
|
+
if (idx >= CNT) {
|
|
91
|
+
printf("add_shmem: too many shmemp\n");
|
|
92
|
+
exit(1);
|
|
93
|
+
}
|
|
94
|
+
key_t key = BASE_KEY + idx;
|
|
95
|
+
int shmid;
|
|
96
|
+
char *data;
|
|
97
|
+
/* create/attach the segment: */
|
|
98
|
+
if ((shmid = shmget(key, CHUNK_SIZE, 0644 | IPC_CREAT)) == -1) {
|
|
99
|
+
perror("shmget");
|
|
100
|
+
exit(1);
|
|
101
|
+
}
|
|
102
|
+
/* attach to the segment to get a pointer to it: */
|
|
103
|
+
data = shmat(shmid, NULL, 0);
|
|
104
|
+
if (data == (char *)(-1)) {
|
|
105
|
+
perror("shmat");
|
|
106
|
+
exit(1);
|
|
107
|
+
}
|
|
108
|
+
MyData.shmemp[idx] = data;
|
|
109
|
+
idx += 1;
|
|
110
|
+
MyData.n_shmem = idx;
|
|
111
|
+
memset(data, 'a', CHUNK_SIZE);
|
|
112
|
+
// printf("add_shmem: bytes=%luK\n", (idx*CHUNK_SIZE)/1024);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
int rm_shmem() {
|
|
116
|
+
int shmid;
|
|
117
|
+
int removed = 0;
|
|
118
|
+
for (int idx = 0; idx < CNT; idx++) {
|
|
119
|
+
key_t key = BASE_KEY + idx;
|
|
120
|
+
if ((shmid = shmget(key, CHUNK_SIZE, 0)) == -1)
|
|
121
|
+
continue;
|
|
122
|
+
if (shmctl(shmid, IPC_RMID, NULL) >= 0)
|
|
123
|
+
removed += 1;
|
|
124
|
+
}
|
|
125
|
+
printf("removed %d segments\n", removed);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
//////////////////////////////// MMAP
|
|
130
|
+
|
|
131
|
+
int add_mmap() {
|
|
132
|
+
int fd;
|
|
133
|
+
unsigned char *ptr;
|
|
134
|
+
if ((fd = MyData.mm_fd) == 0) {
|
|
135
|
+
fd = open(FILENAME, O_RDWR|O_CREAT, 0666);
|
|
136
|
+
if (fd < 0) {
|
|
137
|
+
perror("open(/tmp/...)");
|
|
138
|
+
exit(1);
|
|
139
|
+
}
|
|
140
|
+
MyData.mm_fd = fd;
|
|
141
|
+
int rv = posix_fallocate(fd, 0, CNT*CHUNK_SIZE);
|
|
142
|
+
if (rv < 0) {
|
|
143
|
+
perror("posix_fallocate()");
|
|
144
|
+
exit(1);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if ((ptr = MyData.mm_ptr) == NULL) {
|
|
148
|
+
ptr = mmap(NULL, CNT*CHUNK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
|
149
|
+
if ((long) ptr == -1) {
|
|
150
|
+
perror("mmap()");
|
|
151
|
+
exit(1);
|
|
152
|
+
}
|
|
153
|
+
MyData.mm_ptr = ptr;
|
|
154
|
+
}
|
|
155
|
+
unsigned char* bottom = &ptr[MyData.n_mmap*CHUNK_SIZE];
|
|
156
|
+
memset(bottom, 'm', CHUNK_SIZE);
|
|
157
|
+
MyData.n_mmap += 1;
|
|
158
|
+
// printf("add_mmap: bytes=%luK\n", MyData.n_mmap*CHUNK_SIZE/1024);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
int rm_mmap() {
|
|
162
|
+
unlink(FILENAME);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
//////////////////////////////// MALLOC
|
|
166
|
+
|
|
167
|
+
int add_malloc() {
|
|
168
|
+
MyData.mallocp[MyData.n_malloc] = malloc(CHUNK_SIZE);
|
|
169
|
+
MyData.n_malloc += 1;
|
|
170
|
+
// printf("add_malloc: bytes=%luK\n", MyData.n_malloc*CHUNK_SIZE/1024);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
//////////////////////////////// MAIN LOOP STUFF
|
|
174
|
+
|
|
175
|
+
int loop() {
|
|
176
|
+
void* heap = malloc(CHUNK_SIZE);
|
|
177
|
+
memset(heap, 'h', CHUNK_SIZE);
|
|
178
|
+
char stack[CHUNK_SIZE];
|
|
179
|
+
memset(stack, 'h', CHUNK_SIZE);
|
|
180
|
+
add_shmem();
|
|
181
|
+
add_mmap();
|
|
182
|
+
add_malloc();
|
|
183
|
+
printf("%d: loop=%d, shmem=%luK mmap=%luK stack=%luK heap=%luK\n",
|
|
184
|
+
getpid(),
|
|
185
|
+
LoopCnt+1,
|
|
186
|
+
MyData.n_shmem*CHUNK_SIZE/1024,
|
|
187
|
+
MyData.n_mmap*CHUNK_SIZE/1024,
|
|
188
|
+
MyData.n_mmap*CHUNK_SIZE/1024,
|
|
189
|
+
MyData.n_malloc*CHUNK_SIZE/1024);
|
|
190
|
+
sleep(Args.sleep_sec);
|
|
191
|
+
if (++LoopCnt >= Args.n_loops) {
|
|
192
|
+
exit(0);
|
|
193
|
+
}
|
|
194
|
+
loop(); // NOTE: recurses (to be able to add stack)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
int main(int argc, char *argv[])
|
|
199
|
+
{
|
|
200
|
+
int opt;
|
|
201
|
+
while ((opt = getopt(argc, argv, "qs")) != -1) {
|
|
202
|
+
switch(opt) {
|
|
203
|
+
case 'q': Args.sleep_sec = 1; break;
|
|
204
|
+
case 's': Args.n_loops = 16; break;
|
|
205
|
+
default:
|
|
206
|
+
printf("USE: %s {-qs} # quick,short", argv[0]);
|
|
207
|
+
exit(1);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
memset(&MyData, 0, sizeof(MyData));
|
|
211
|
+
incr_sem();
|
|
212
|
+
loop();
|
|
213
|
+
|
|
214
|
+
return 0;
|
|
215
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["flit_core>=3.4"]
|
|
3
|
+
build-backend = "flit_core.buildapi"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "pmemstat"
|
|
7
|
+
version = "2.3.29"
|
|
8
|
+
description = "Report Proportional Memory on Linux"
|
|
9
|
+
authors = [
|
|
10
|
+
{name = "Joe Defen", email = "joedef@duck.com"},
|
|
11
|
+
]
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
license = { text = "MIT" }
|
|
14
|
+
requires-python = ">=3.8"
|
|
15
|
+
keywords = ["proportional memory", "RAM", "htop", "top", "monitor"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Operating System :: POSIX :: Linux"
|
|
20
|
+
]
|
|
21
|
+
dependencies = [
|
|
22
|
+
'psutil>5.9',
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[project.urls]
|
|
26
|
+
"Homepage" = "https://github.com/joedefen/pmemstat"
|
|
27
|
+
"Bug Tracker" = "https://github.com/joedefen/pmemstat/issues"
|
|
28
|
+
|
|
29
|
+
[project.scripts]
|
|
30
|
+
pmemstat = "pmemstat.main:run"
|
pmemstat-2.3.29/run.sh
ADDED
pmemstat-2.3.28/PKG-INFO
DELETED
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: pmemstat
|
|
3
|
-
Version: 2.3.28
|
|
4
|
-
Summary: Report Proportional Memory on Linux
|
|
5
|
-
Author-email: Joe Defen <joedef@duck.com>
|
|
6
|
-
License: MIT
|
|
7
|
-
Project-URL: Homepage, https://github.com/joedefen/pmemstat
|
|
8
|
-
Project-URL: Bug Tracker, https://github.com/joedefen/pmemstat/issues
|
|
9
|
-
Keywords: proportional memory,RAM,htop,top,monitor
|
|
10
|
-
Classifier: Programming Language :: Python :: 3
|
|
11
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
-
Classifier: Operating System :: POSIX :: Linux
|
|
13
|
-
Requires-Python: >=3.8
|
|
14
|
-
Description-Content-Type: text/markdown
|
|
15
|
-
License-File: LICENSE.txt
|
|
16
|
-
Requires-Dist: psutil>5.9
|
|
17
|
-
|
|
18
|
-
> **Quick Start**: from the CLI
|
|
19
|
-
> * **If `python3 -V` shows v3.11 or later, install with `pipx`**:
|
|
20
|
-
> * install `pipx` per your distro's guidance
|
|
21
|
-
> * then: `pipx upgrade pmemstat || pipx install pmemstat`
|
|
22
|
-
> * **Else for python3.10 and lesser versions, install with `pip`**:
|
|
23
|
-
> * install `pip` per your distro's guidance
|
|
24
|
-
> * then: `python3 -m pip install --user --upgrade pmemstat`
|
|
25
|
-
> * **To run**:
|
|
26
|
-
> * simply run: `pmemstat`
|
|
27
|
-
> * type "?" within `pmemstat` to show help screen.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
# pmemstat - Proportional Memory Status
|
|
31
|
-
|
|
32
|
-
`pmemstat` shows detailed **proportional** memory use of **Linux** processes by digesting:
|
|
33
|
-
* `/proc/{PID}/smaps`
|
|
34
|
-
* `/proc/{PID}/smaps_rollup`
|
|
35
|
-
|
|
36
|
-
Computing proportional memory avoids overstating memory use as many programs do (e.g., `top`). Specifically, proportional memory splits the cost of common memory to the processes sharing it (rather than counting common memory multiple times). And, it does not include uninstantiated virtual memory.
|
|
37
|
-
|
|
38
|
-
Without `-o`, `pmemstat` shows less details and is much faster and sometimes less accurate (e.g., it will not report classes of memory such as SysV shared memory which are often are not present anyhow). With `-o` providing full detail, digging out the numbers is slower; thus, `pmemstat -o` may take a few seconds to start, but, in its loop mode, refreshes are relatively fast and efficient by avoiding recomputing unchanged numbers. When in its window mode, typing `o` toggles low/high detail.
|
|
39
|
-
|
|
40
|
-
`pmemstat`'s grouping feature rolls up the resources of multiple processes of a feature (e.g., a browser) to make the total memory/cpu impact much more apparent.
|
|
41
|
-
|
|
42
|
-
Its looping features allow monitoring for changes in memory growth which may be "leaks". Segregating memory by types can make identifying leaks faster and more certain.
|
|
43
|
-
|
|
44
|
-
**In version 2.0, `pmemstat` has many new features including**:
|
|
45
|
-
* In its **window mode**, `pmemstat` updates the terminal in place (using "curses") rather than scrolling.
|
|
46
|
-
* Showing **CPU use**, too, which makes `pmemstat` a viable alternative to `top` for regular use (although more specialized and still focused on accurate memory representation).
|
|
47
|
-
* Supports **killing processes** that are selected visually with confirmation they are really gone (or not).
|
|
48
|
-
* And several **new options** that can be **controlled dynamically** if in window mode.
|
|
49
|
-
|
|
50
|
-
## Installation Options
|
|
51
|
-
Note that:
|
|
52
|
-
* `pmemstat` needs to run as root to read the memory statistics for all processes (which is normally desired).
|
|
53
|
-
* By default, `pmemstat` reruns itself as with `sudo` (thus you need `sudo` privileges).
|
|
54
|
-
* To defeat re-running with `sudo`, use the `--run-as-user` or `-U` option.
|
|
55
|
-
|
|
56
|
-
See the Quick Start at the top for preferred install instructions using `pipx`. If not acceptable, see the "Alternative Installation Options" section below.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
## Usage
|
|
60
|
-
```
|
|
61
|
-
usage: pmemstat [-h] [-D] [-C] [-g {exe,cmd,pid}] [-f] [-k MIN_DELTA_KB]
|
|
62
|
-
[-l LOOP_SECS] [-L CMDLEN] [-t TOP_PCT] [-n] [-U] [-o]
|
|
63
|
-
[-u {MB,mB,KB,human}] [-R] [-s {mem,cpu,name}] [-/ SEARCH] [-W] [pids ...]
|
|
64
|
-
|
|
65
|
-
positional arguments:
|
|
66
|
-
pids list of pids/groups (none means every accessible pid)
|
|
67
|
-
|
|
68
|
-
options:
|
|
69
|
-
-h, --help show this help message and exit
|
|
70
|
-
-D, --debug debug mode (the more Ds, the higher the debug level)
|
|
71
|
-
-C, --no-cpu do NOT report percent CPU (only in window mode)
|
|
72
|
-
-g {exe,cmd,pid}, --groupby {exe,cmd,pid}
|
|
73
|
-
grouping method for presenting rows
|
|
74
|
-
-f, --fit-to-window do not overflow window [if -w]
|
|
75
|
-
-k MIN_DELTA_KB, --min-delta-kb MIN_DELTA_KB
|
|
76
|
-
minimum delta KB to show again [dflt=100 if DB else 1000
|
|
77
|
-
-l LOOP_SECS, --loop LOOP_SECS
|
|
78
|
-
loop interval in secs [dflt=5 if -w else 0]
|
|
79
|
-
-L CMDLEN, --cmdlen CMDLEN
|
|
80
|
-
max shown command length [dflt=36 if not -w]
|
|
81
|
-
-t TOP_PCT, --top-pct TOP_PCT
|
|
82
|
-
report group contributing to top pct of ptotal [dflt=100]
|
|
83
|
-
-n, --numbers show line numbers in report
|
|
84
|
-
-U, --run-as-user run as user (NOT as root)
|
|
85
|
-
-o, --others collapse shSYSV, shOth, stack, text into "other"
|
|
86
|
-
-u {MB,mB,KB,human}, --units {MB,mB,KB,human}
|
|
87
|
-
units of memory [dflt=MB]
|
|
88
|
-
-R, --no-rise do NOT raise change/adds to top (only in window mode)
|
|
89
|
-
-s {mem,cpu,name}, --sortby {mem,cpu,name}
|
|
90
|
-
grouping method for presenting rows
|
|
91
|
-
-/ SEARCH, --search SEARCH
|
|
92
|
-
show items with search string in name
|
|
93
|
-
-W, --no-window show in "curses" window [disables: -D,-t,-L]
|
|
94
|
-
|
|
95
|
-
```
|
|
96
|
-
Explanation of some options and arguments:
|
|
97
|
-
* `-g {exe,cmd,pid}, --groupby {exe,cmd,pid}` - select the grouping of memory stats for reporting.
|
|
98
|
-
* `exe` - group by basename of the executable (the default)
|
|
99
|
-
* `cmd` - group by the truncated command line (use `-L CMDLEN` to choose length)
|
|
100
|
-
* `pid` - group by one process
|
|
101
|
-
* `-k MIN_DELTA_KB, --min-delta-kb MIN_DELTA_KB` - when looping, how much change in memory use is required to show the grouping in subsequent loops; note:
|
|
102
|
-
* a positive `MIN_DELTA_KB` means the total memory of the groupin must **grow** by that amount (in KB)
|
|
103
|
-
* a non-positive `MIN_DELTA_KB` means the total memory of the grouping must **change** by that amount (in KB)
|
|
104
|
-
* `pids` - the positional arguments may be pids (i.e., numbers) or the names of executables (as shown by `-gexe`)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
## Example Usage with Explanation of Output
|
|
108
|
-

|
|
109
|
-
|
|
110
|
-
In the default refreshed window loop, we see
|
|
111
|
-
* a **leader line** with:
|
|
112
|
-
* the current time
|
|
113
|
-
* from `/proc/meminfo` in MemTotal (Tot), MemAvailable (Avail), Tmp (Shmem+TmpFS), and Dirty.
|
|
114
|
-
* 'Oth' is the unaccounted for memory belonging to the kernel, reserve,
|
|
115
|
-
drivers, imprecision, etc.; `Oth = Tot - Avail - Tmp - ptotal`.
|
|
116
|
-
* Features such as BTRFS, ZFS, zRAM, unattached SysV Shared Memory, etc., can cause 'Oth' to be significant;
|
|
117
|
-
that is, MemAvail is often greatly understated (and 'Oth' is overstated). As a test (not intended for regular use), try:
|
|
118
|
-
`sudo sync; sudo sh -c "echo 3 > /proc/sys/vm/drop_caches"`; if that reduces `Oth` significantly,
|
|
119
|
-
then the MemAvailable calculation was off significantly.
|
|
120
|
-
* Determining the contributors can be difficult, but start with `sudo slabtop -sc` and feature specific tools (e.g., `zpool list`).
|
|
121
|
-
* how many PIDs are contributing to the report vs the total number of PIDs excluding kernel threads
|
|
122
|
-
* a **second leader line for zRAM** only if zRAM is active with:
|
|
123
|
-
* percent cpu consumed by kernel processes (not normalized ... if there 4 CPUs, then the total CPU can 400%). This is important because, with zRAM, this often is mostly the swap process.
|
|
124
|
-
* **zRAM** - the amount of "Used" RAM that is storing zRAM data
|
|
125
|
-
* **eTot** - the effective Total RAM and the percent of "Tot" RAM (which would typically be above 100%). The bigger **zRAM**, the more accurate this number.
|
|
126
|
-
* **eUsed** - the effective Used RAM and percent of "Tot" RAM.
|
|
127
|
-
* **eAvail** - the effective Available RAM and percent of "Tot" RAM.
|
|
128
|
-
* a **header line with the reported fields** including:
|
|
129
|
-
* **cpu** - percent CPU (again not normalized to 100%)
|
|
130
|
-
* **pswap** - proportional use of swap (per smaps_rollup)
|
|
131
|
-
* **other** - partly sums these categories (shown by the key, `o`):
|
|
132
|
-
* **shSYSV** - proportional use of System V shared memory (per smaps)
|
|
133
|
-
* **shOth** - proportional use of other shared memory (per smaps)
|
|
134
|
-
* **stack** - exclusive use of stack memory per smaps
|
|
135
|
-
* **text** - proportional use of memory for text (i.e., the read-only binary code, per smaps)
|
|
136
|
-
* **data** - exclusive use of memory for data (i.e., exclusively used of "heap" memory, per smaps)
|
|
137
|
-
* **ptotal** - proportional use of memory of all categories (i.e, sum of columns to the left); **note**, if zRAM, this includes **pswap**, else not.
|
|
138
|
-
* *empty* - type of the entry which may be:
|
|
139
|
-
* **T** - the grand total
|
|
140
|
-
* **A** - a newly added grouping
|
|
141
|
-
* **O** - combined overflow groupings below the `--top-pct` threshold (only on first loop)
|
|
142
|
-
* **+-{number}K** - number of KB of change in **ptotal** (only on subsequent loops)
|
|
143
|
-
* **key/info** which is a quantifier plus the grouping key. The quantifier may be:
|
|
144
|
-
* **{PID}** - when the grouping line represents one process (for option `-gexe`).
|
|
145
|
-
* **{num}x** - where {num} is the number of processes in the grouping.
|
|
146
|
-
|
|
147
|
-
## Help Screen (in Window Mode, Press '?')
|
|
148
|
-
In window mode, press '?' to enter the help screen which looks like:
|
|
149
|
-
|
|
150
|
-

|
|
151
|
-
|
|
152
|
-
**Notes:**
|
|
153
|
-
* There are a number of navigation keys (mostly following vim conventions); in the help screen, they apply to help screen; otherwise, they apply to main screen.
|
|
154
|
-
* Below the line, there are a number of keys/options; when you type an option key (e.g, "c"), it will highlight the next option value (e.g., "off"); when you change options, they will be applied to the next loop of the main menu.
|
|
155
|
-
* These option keys can be used in the main menu (e.g., pressing "c" will change hide or reveal the CPU column w/o entering the help screen).
|
|
156
|
-
|
|
157
|
-
## Kill Mode (Window Mode)
|
|
158
|
-
Pressing "K" enter "Kill Mode" where you use the navigation keys to highlight a row, and then press ENTER to kill the process(es) represented by that row.
|
|
159
|
-
|
|
160
|
-
## Scroll Position (Window Mode)
|
|
161
|
-
|
|
162
|
-
Sometimes, the horizontal line between the header and scrollable region has a reverse video block (under the "351" in this case):
|
|
163
|
-

|
|
164
|
-
|
|
165
|
-
**Notes:**
|
|
166
|
-
* When there is no block, the scrolled document does not overflow the scrollable region.
|
|
167
|
-
* When there is a block, its position indicates:
|
|
168
|
-
* **Leftmost** - At the top of the document.
|
|
169
|
-
* **Rightmost** - At the bottom of the document.
|
|
170
|
-
* **Between Leftmost and Rightmost** - At percentage of the document approximated by its position from Left (0%) to Right (100%).
|
|
171
|
-
* Its length indicates, roughly, how much of the entire document you can see.
|
|
172
|
-
* Again, you can press 'f' to fit the document to the screen with a "rollup" line summarizing the lines that would not fit.
|
|
173
|
-
|
|
174
|
-
## Quirks and Details
|
|
175
|
-
* **pswap** seems to be only provided by the `smaps_rollups` file, and thus it may be slightly out of sync with the data gathered by `smaps`.
|
|
176
|
-
* the **ptotal** (from 'smaps') and **pss** (from `smaps_rollups` and usually hidden) seem differ more than expected but still close.
|
|
177
|
-
* after the first loop, **pss** is read and only groups with sufficient aggregate change are probed for the details. Thus, subsequent loops are more efficient by avoiding the reading of `smaps` in many cases (with some loss of accuracy).
|
|
178
|
-
* the "exe" value comes from the command line (based `/proc/{PID}/cmdline` which is a bit funky). Firstly, the leading path is stripped; secondly, if the resulting executable is a script interpreter (e.g., python, perl, bash, ...) AND the first argument seems to be a full path (i.e., starts with "/"), then the "exe" will be represented as "{interpreter}->{basename(script)}". For example, "python3->pmemstat.py" in the example above.
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
## Test Program and Test Suggestions
|
|
182
|
-
The C program, `memtest.c` is included and can be compiled by running `cc memtest.c -o memtest`. This program:
|
|
183
|
-
* regularly allocates more memory of all types
|
|
184
|
-
* can be run several times simultaneously,
|
|
185
|
-
* will share SysV shared memory and memory mapped files,
|
|
186
|
-
|
|
187
|
-
When running `pmemstat` to monitor its memory use and changes, you should use `-uKB` and `-k{small-number}` so that you can "see" the very modest memory use of the test program and its changes.
|
|
188
|
-
|
|
189
|
-
Running a number of sleeps of various durations in the background in a loop, plus one foreground sleep, can make for a robustness tests with lots of processes coming and going. There are many "races" (i.e., a process may appear in `/proc`, but its`smaps` is gone), and this test helps ensure the races are handled properly.
|
|
190
|
-
|
|
191
|
-
## Alternative Installation Options
|
|
192
|
-
If the `pipx` install is not acceptable, choose the best way to install:
|
|
193
|
-
* **From PyPi as non-root**. You need `~/.local/bin` on your `$PATH`.
|
|
194
|
-
```
|
|
195
|
-
python -m pip install --user pmemstat
|
|
196
|
-
# to uninstall: python -m pip uninstall pmemstat
|
|
197
|
-
```
|
|
198
|
-
* Or **from PyPi as root**. This makes `pmemstat` available to all users with `/usr/local/bin` on `$PATH`. Note: `PIP_BREAK_SYSTEM_PACKAGES=1` may be required on some distros.
|
|
199
|
-
```
|
|
200
|
-
PIP_BREAK_SYSTEM_PACKAGES=1 sudo python -m pip install pmemstat
|
|
201
|
-
# to uninstall: sudo python -m pip uninstall pmemstat
|
|
202
|
-
```
|
pmemstat-2.3.28/pyproject.toml
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
# HOW TO PUBLISH...
|
|
2
|
-
#
|
|
3
|
-
# Prep Work (ensure need modules are up-to-date):
|
|
4
|
-
# sudo pacman -Syu python-pip
|
|
5
|
-
# sudo pacman -Syu python-build
|
|
6
|
-
# sudo pacman -Syu python-twine
|
|
7
|
-
# -- antiquated way
|
|
8
|
-
# python3 -m pip install --upgrade pip
|
|
9
|
-
# python3 -m pip install --upgrade build
|
|
10
|
-
# python3 -m pip install --upgrade twine
|
|
11
|
-
#
|
|
12
|
-
# PUBLIC Build and deploy (from project directory):
|
|
13
|
-
# ## BUMP the version (below in [project])
|
|
14
|
-
# rm -r dist; python3 -m build; ls dist/.
|
|
15
|
-
# python3 -m twine upload dist/*
|
|
16
|
-
# ## Enter __token__ and the saved TOKEN (in bitwarden)
|
|
17
|
-
# pipx upgrade pmemstat || pipx install pmemstat # >= python3.11
|
|
18
|
-
# --OR-- sudo python3 -m pip install pmemstat # <= python3.10
|
|
19
|
-
# ## VISIT https://pypi.org/project/pmemstat and delete old versions
|
|
20
|
-
#
|
|
21
|
-
# TEST Build and test (from project directory):
|
|
22
|
-
# ## BUMP the version (below in [project])
|
|
23
|
-
# rm -r dist; python3 -m build
|
|
24
|
-
# python3 -m twine upload --repository testpypi dist/*
|
|
25
|
-
# ## Enter __token__ and the saved TOKEN (in bitwarden)
|
|
26
|
-
# sudo python3 -m pip install --index-url https://test.pypi.org/simple/ --no-deps pmemstat
|
|
27
|
-
# ## VISIT https://test.pypi.org/project/pmemstat and delete old versions
|
|
28
|
-
|
|
29
|
-
[build-system]
|
|
30
|
-
requires = ["setuptools>=42", "wheel"]
|
|
31
|
-
build-backend = "setuptools.build_meta"
|
|
32
|
-
|
|
33
|
-
[project]
|
|
34
|
-
name = "pmemstat"
|
|
35
|
-
version = "2.3.28"
|
|
36
|
-
description = "Report Proportional Memory on Linux"
|
|
37
|
-
authors = [
|
|
38
|
-
{name = "Joe Defen", email = "joedef@duck.com"},
|
|
39
|
-
]
|
|
40
|
-
readme = "README.md"
|
|
41
|
-
license = { text = "MIT" }
|
|
42
|
-
requires-python = ">=3.8"
|
|
43
|
-
|
|
44
|
-
keywords = ["proportional memory", "RAM", "htop", "top", "monitor"]
|
|
45
|
-
|
|
46
|
-
classifiers = [
|
|
47
|
-
"Programming Language :: Python :: 3",
|
|
48
|
-
"License :: OSI Approved :: MIT License",
|
|
49
|
-
"Operating System :: POSIX :: Linux"
|
|
50
|
-
]
|
|
51
|
-
|
|
52
|
-
dependencies = [
|
|
53
|
-
'psutil>5.9',
|
|
54
|
-
]
|
|
55
|
-
|
|
56
|
-
[project.urls]
|
|
57
|
-
"Homepage" = "https://github.com/joedefen/pmemstat"
|
|
58
|
-
"Bug Tracker" = "https://github.com/joedefen/pmemstat/issues"
|
|
59
|
-
|
|
60
|
-
[project.scripts]
|
|
61
|
-
pmemstat = "pmemstat.main:run"
|
|
62
|
-
|
|
63
|
-
[tool.setuptools]
|
|
64
|
-
package-dir = {"" = "src"}
|
|
65
|
-
|
|
66
|
-
[tool.setuptools.packages.find]
|
|
67
|
-
where = ["src"]
|
|
68
|
-
|
|
69
|
-
[tool.setuptools.package-data]
|
|
70
|
-
exclude = [
|
|
71
|
-
"__pycache__",
|
|
72
|
-
]
|
pmemstat-2.3.28/setup.cfg
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
LICENSE.txt
|
|
2
|
-
README.md
|
|
3
|
-
pyproject.toml
|
|
4
|
-
src/pmemstat/CpuSmooth.py
|
|
5
|
-
src/pmemstat/KillThem.py
|
|
6
|
-
src/pmemstat/Window.py
|
|
7
|
-
src/pmemstat/__init__.py
|
|
8
|
-
src/pmemstat/main.py
|
|
9
|
-
src/pmemstat.egg-info/PKG-INFO
|
|
10
|
-
src/pmemstat.egg-info/SOURCES.txt
|
|
11
|
-
src/pmemstat.egg-info/dependency_links.txt
|
|
12
|
-
src/pmemstat.egg-info/entry_points.txt
|
|
13
|
-
src/pmemstat.egg-info/requires.txt
|
|
14
|
-
src/pmemstat.egg-info/top_level.txt
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
psutil>5.9
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
pmemstat
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|