pmemstat 3.0.3__tar.gz → 3.0.4__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-3.0.3 → pmemstat-3.0.4}/PKG-INFO +3 -4
- {pmemstat-3.0.3 → pmemstat-3.0.4}/pmemstat/main.py +114 -25
- {pmemstat-3.0.3 → pmemstat-3.0.4}/pyproject.toml +2 -2
- pmemstat-3.0.4/runner +17 -0
- pmemstat-3.0.3/run.sh +0 -9
- {pmemstat-3.0.3 → pmemstat-3.0.4}/.gitignore +0 -0
- {pmemstat-3.0.3 → pmemstat-3.0.4}/LICENSE.txt +0 -0
- {pmemstat-3.0.3 → pmemstat-3.0.4}/README.md +0 -0
- {pmemstat-3.0.3 → pmemstat-3.0.4}/TODO.md +0 -0
- {pmemstat-3.0.3 → pmemstat-3.0.4}/images/help-screen.png +0 -0
- {pmemstat-3.0.3 → pmemstat-3.0.4}/images/pmemstat.png +0 -0
- {pmemstat-3.0.3 → pmemstat-3.0.4}/images/scroll-pos.png +0 -0
- {pmemstat-3.0.3 → pmemstat-3.0.4}/memtest.c +0 -0
- {pmemstat-3.0.3 → pmemstat-3.0.4}/pmemstat/CpuSmooth.py +0 -0
- {pmemstat-3.0.3 → pmemstat-3.0.4}/pmemstat/KillThem.py +0 -0
- {pmemstat-3.0.3 → pmemstat-3.0.4}/pmemstat/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
2
|
Name: pmemstat
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.4
|
|
4
4
|
Summary: Report Proportional Memory on Linux
|
|
5
5
|
Keywords: proportional memory,RAM,htop,top,monitor
|
|
6
6
|
Author-email: Joe Defen <joedef@duck.com>
|
|
@@ -9,9 +9,8 @@ Description-Content-Type: text/markdown
|
|
|
9
9
|
Classifier: Programming Language :: Python :: 3
|
|
10
10
|
Classifier: License :: OSI Approved :: MIT License
|
|
11
11
|
Classifier: Operating System :: POSIX :: Linux
|
|
12
|
-
License-File: LICENSE.txt
|
|
13
12
|
Requires-Dist: psutil > 5.9
|
|
14
|
-
Requires-Dist: console-window >= 1.0.
|
|
13
|
+
Requires-Dist: console-window >= 1.0.5
|
|
15
14
|
Project-URL: Bug Tracker, https://github.com/joedefen/pmemstat/issues
|
|
16
15
|
Project-URL: Homepage, https://github.com/joedefen/pmemstat
|
|
17
16
|
|
|
@@ -94,6 +94,92 @@ def human(number):
|
|
|
94
94
|
return f'{number:.1f}{suffix}'
|
|
95
95
|
return '' # impossible, but make pylint happy
|
|
96
96
|
|
|
97
|
+
####################################################################################
|
|
98
|
+
# PORTABLE FUNCTION - Copy-pasted from zram-advisor
|
|
99
|
+
# When updating: copy entire function from zram_advisor/main.py (lines 86-166)
|
|
100
|
+
####################################################################################
|
|
101
|
+
def compute_zram_effective(meminfo_total, meminfo_used, meminfo_available,
|
|
102
|
+
zram_orig_data_size, zram_mem_used_total,
|
|
103
|
+
zram_disksize, zram_mem_limit=0, limit_pct=80):
|
|
104
|
+
"""
|
|
105
|
+
Compute effective memory values accounting for zRAM compression.
|
|
106
|
+
|
|
107
|
+
This is a PORTABLE function that can be copy-pasted between projects.
|
|
108
|
+
NO class dependencies - all inputs passed as parameters.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
meminfo_total: Total physical RAM in bytes
|
|
112
|
+
meminfo_used: Currently used RAM in bytes
|
|
113
|
+
meminfo_available: Available RAM in bytes
|
|
114
|
+
zram_orig_data_size: Uncompressed data size stored in zRAM (bytes)
|
|
115
|
+
zram_mem_used_total: Physical RAM consumed by zRAM including overhead (bytes)
|
|
116
|
+
zram_disksize: Max uncompressed data zRAM will accept (bytes)
|
|
117
|
+
zram_mem_limit: Max RAM zRAM can use (0=unlimited) (bytes)
|
|
118
|
+
limit_pct: Arbitrary limit on % of RAM zRAM should use (default 80%)
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
SimpleNamespace with:
|
|
122
|
+
- e_used: Effective memory used (uncompressed equivalent)
|
|
123
|
+
- e_avail: Effective memory available
|
|
124
|
+
- e_max_used: Maximum effective memory at full zRAM capacity
|
|
125
|
+
- ratio_current: Current effective compression ratio
|
|
126
|
+
- ratio_projected: Projected ratio accounting for degradation
|
|
127
|
+
- projection_confidence: 'low', 'medium', or 'high'
|
|
128
|
+
- usage_fraction: Fraction of disksize currently used
|
|
129
|
+
"""
|
|
130
|
+
# Calculate effective used memory (what it would be if uncompressed)
|
|
131
|
+
e_used = meminfo_used - zram_mem_used_total + zram_orig_data_size
|
|
132
|
+
|
|
133
|
+
# Determine compression ratio
|
|
134
|
+
ratio = None
|
|
135
|
+
if e_used <= meminfo_used: # zRAM not helping yet
|
|
136
|
+
e_used = meminfo_used
|
|
137
|
+
ratio = 2.75 # Conservative guess for projection when no data yet
|
|
138
|
+
|
|
139
|
+
if ratio is None: # Calculate actual ratio
|
|
140
|
+
ratio = zram_orig_data_size / zram_mem_used_total if zram_mem_used_total > 0 else 2.75
|
|
141
|
+
|
|
142
|
+
# Apply memory limit if configured
|
|
143
|
+
if zram_mem_limit > 0:
|
|
144
|
+
stats_limit_pct = (zram_mem_limit / meminfo_total) * 100
|
|
145
|
+
limit_pct = min(100.0, limit_pct, stats_limit_pct)
|
|
146
|
+
|
|
147
|
+
# Calculate usage fraction and apply degradation
|
|
148
|
+
usage_fraction = zram_orig_data_size / zram_disksize if zram_disksize > 0 else 0
|
|
149
|
+
|
|
150
|
+
# Degradation logic based on current usage
|
|
151
|
+
if usage_fraction < 0.10:
|
|
152
|
+
degradation_factor = 0.75 # Aggressive: little real data
|
|
153
|
+
confidence = "low"
|
|
154
|
+
elif usage_fraction < 0.50:
|
|
155
|
+
degradation_factor = 0.85 # Moderate: some real data
|
|
156
|
+
confidence = "medium"
|
|
157
|
+
else:
|
|
158
|
+
degradation_factor = 0.95 # Conservative: lots of real data
|
|
159
|
+
confidence = "high"
|
|
160
|
+
|
|
161
|
+
projected_ratio = ratio * degradation_factor
|
|
162
|
+
|
|
163
|
+
# Project maximum effective memory when zRAM fills to limit
|
|
164
|
+
e_max_used = projected_ratio * meminfo_total * limit_pct / 100
|
|
165
|
+
# Cap by disksize limit
|
|
166
|
+
e_max_used = min(e_max_used, zram_disksize)
|
|
167
|
+
# Add uncompressed memory not in zRAM
|
|
168
|
+
e_max_used += meminfo_total - e_max_used / projected_ratio
|
|
169
|
+
|
|
170
|
+
# Calculate effective available
|
|
171
|
+
e_avail = e_max_used - e_used
|
|
172
|
+
|
|
173
|
+
return SimpleNamespace(
|
|
174
|
+
e_used=e_used,
|
|
175
|
+
e_avail=e_avail,
|
|
176
|
+
e_max_used=e_max_used,
|
|
177
|
+
ratio_current=ratio,
|
|
178
|
+
ratio_projected=projected_ratio,
|
|
179
|
+
projection_confidence=confidence,
|
|
180
|
+
usage_fraction=usage_fraction
|
|
181
|
+
)
|
|
182
|
+
|
|
97
183
|
####################################################################################
|
|
98
184
|
###### ZramProjector class
|
|
99
185
|
####################################################################################
|
|
@@ -156,7 +242,7 @@ class ZramProjector:
|
|
|
156
242
|
return infos
|
|
157
243
|
|
|
158
244
|
def compute_effective(self, meminfoKB):
|
|
159
|
-
""" Compute the effective values """
|
|
245
|
+
""" Compute the effective values - now uses portable function """
|
|
160
246
|
def seed(meminfoKB):
|
|
161
247
|
nonlocal self
|
|
162
248
|
meminfo = self.meminfo = SimpleNamespace()
|
|
@@ -175,6 +261,8 @@ class ZramProjector:
|
|
|
175
261
|
devs = self._get_zram_stats()
|
|
176
262
|
if not devs:
|
|
177
263
|
return
|
|
264
|
+
|
|
265
|
+
# Aggregate stats from all zRAM devices
|
|
178
266
|
stats = None
|
|
179
267
|
for stat in devs.values():
|
|
180
268
|
# NOTE: generalization for more than one weak unless all
|
|
@@ -187,29 +275,25 @@ class ZramProjector:
|
|
|
187
275
|
stats = SimpleNamespace(**stats)
|
|
188
276
|
self.meminfo.MemZram = stats.mem_used_total
|
|
189
277
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
e_max_used =
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
e_max_used += meminfo.MemTotal - e_max_used/ratio
|
|
210
|
-
self.e_max_used = e_max_used
|
|
211
|
-
# self.e_max_used = max(e_max_total, e_max_used)
|
|
212
|
-
self.e_avail = e_max_used - e_used
|
|
278
|
+
# Call the portable computation function
|
|
279
|
+
result = compute_zram_effective(
|
|
280
|
+
meminfo_total=meminfo.MemTotal,
|
|
281
|
+
meminfo_used=meminfo.MemUsed,
|
|
282
|
+
meminfo_available=meminfo.MemAvailable,
|
|
283
|
+
zram_orig_data_size=stats.orig_data_size,
|
|
284
|
+
zram_mem_used_total=stats.mem_used_total,
|
|
285
|
+
zram_disksize=stats.disksize,
|
|
286
|
+
zram_mem_limit=stats.mem_limit,
|
|
287
|
+
limit_pct=self.limit_pct
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
# Update instance variables from result
|
|
291
|
+
self.e_used = result.e_used
|
|
292
|
+
self.e_avail = result.e_avail
|
|
293
|
+
self.e_max_used = result.e_max_used
|
|
294
|
+
self.ratio = result.ratio_current
|
|
295
|
+
self.ratio_projected = result.ratio_projected
|
|
296
|
+
self.projection_confidence = result.projection_confidence
|
|
213
297
|
|
|
214
298
|
|
|
215
299
|
####################################################################################
|
|
@@ -1314,7 +1398,12 @@ def rerun_module_as_root(module_name):
|
|
|
1314
1398
|
""" rerun using the module name """
|
|
1315
1399
|
if os.geteuid() != 0: # Re-run the script with sudo
|
|
1316
1400
|
os.chdir(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
1317
|
-
|
|
1401
|
+
# Preserve PYTHONPATH to allow sudo to find user-installed packages
|
|
1402
|
+
pythonpath = os.pathsep.join(sys.path)
|
|
1403
|
+
env_vars = os.environ.copy()
|
|
1404
|
+
env_vars['PYTHONPATH'] = pythonpath
|
|
1405
|
+
# Use env to pass PYTHONPATH through sudo
|
|
1406
|
+
vp = ['sudo', 'env', f'PYTHONPATH={pythonpath}', sys.executable, '-m', module_name] + sys.argv[1:]
|
|
1318
1407
|
os.execvp('sudo', vp)
|
|
1319
1408
|
|
|
1320
1409
|
def main():
|
|
@@ -4,7 +4,7 @@ build-backend = "flit_core.buildapi"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pmemstat"
|
|
7
|
-
version = "3.0.
|
|
7
|
+
version = "3.0.4"
|
|
8
8
|
description = "Report Proportional Memory on Linux"
|
|
9
9
|
authors = [
|
|
10
10
|
{name = "Joe Defen", email = "joedef@duck.com"},
|
|
@@ -20,7 +20,7 @@ classifiers = [
|
|
|
20
20
|
]
|
|
21
21
|
dependencies = [
|
|
22
22
|
'psutil > 5.9',
|
|
23
|
-
'console-window >= 1.0.
|
|
23
|
+
'console-window >= 1.0.5',
|
|
24
24
|
]
|
|
25
25
|
|
|
26
26
|
[project.urls]
|
pmemstat-3.0.4/runner
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# runner.py
|
|
3
|
+
# Located in the top-level <svr pmemstat> directory
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
# Add the project directory to PYTHONPATH for editable install support
|
|
9
|
+
project_dir = os.path.dirname(os.path.abspath(__file__))
|
|
10
|
+
if project_dir not in sys.path:
|
|
11
|
+
sys.path.insert(0, project_dir)
|
|
12
|
+
|
|
13
|
+
# Import and run the main module directly
|
|
14
|
+
if __name__ == '__main__':
|
|
15
|
+
sys.argv[0] = 'pmemstat'
|
|
16
|
+
from pmemstat import main
|
|
17
|
+
main.run()
|
pmemstat-3.0.3/run.sh
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|