mirror of
https://github.com/nicolargo/glances.git
synced 2026-10-08 01:42:01 -04:00
Merge branch 'Dipet-perf/lazy-process-views' into develop
This commit is contained in:
commit
bbb4176eca
2 files changed
+106
No files matched your search
@@ -122,6 +122,9 @@ class ProcesslistPlugin(GlancesPluginModel):
|
||||
stats is a list
|
||||
"""
|
||||
|
||||
# True between a refresh and the first read of the views, see update_views()
|
||||
_views_pending = False
|
||||
|
||||
# Default list of processes stats to be grabbed / displayed
|
||||
# Can be altered by glances_processes.disable_stats
|
||||
enable_stats = [
|
||||
@@ -259,6 +262,34 @@ class ProcesslistPlugin(GlancesPluginModel):
|
||||
|
||||
return self.stats
|
||||
|
||||
def update_views(self):
|
||||
"""Note that the views are out of date, without building them.
|
||||
|
||||
The list holds every process on the machine, while the UI shows a few dozen rows and
|
||||
msg_curse() builds its own decorations rather than reading the views. Only the API
|
||||
asks for them, so building them on every refresh is work nobody collects.
|
||||
"""
|
||||
self._views_pending = True
|
||||
self.views = {}
|
||||
return self.views
|
||||
|
||||
def get_views(self, item=None, key=None, option=None):
|
||||
"""Build the views if the last refresh left them pending, then answer as usual."""
|
||||
if self._views_pending:
|
||||
self._views_pending = False
|
||||
super().update_views()
|
||||
return super().get_views(item=item, key=key, option=option)
|
||||
|
||||
def set_views(self, input_views):
|
||||
"""Views handed to us replace whatever a pending build would have produced."""
|
||||
self._views_pending = False
|
||||
super().set_views(input_views)
|
||||
|
||||
def reset_views(self):
|
||||
"""A reset must stay reset; without this the next read would rebuild them."""
|
||||
self._views_pending = False
|
||||
super().reset_views()
|
||||
|
||||
def get_api(self):
|
||||
"""Return the sorted processes list for the API."""
|
||||
return glances_processes.get_list(sorted=True)
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
"""Tests for the lazily built process views."""
|
||||
|
||||
import json
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def make_process(pid):
|
||||
return {
|
||||
'pid': pid,
|
||||
'key': 'pid',
|
||||
'name': f'proc{pid}',
|
||||
'cmdline': [f'proc{pid}'],
|
||||
'username': 'someone',
|
||||
'status': 'S',
|
||||
'nice': 0,
|
||||
'num_threads': 1,
|
||||
'cpu_percent': 0.0,
|
||||
'memory_percent': 0.1,
|
||||
'memory_info': {'rss': 1024, 'vms': 2048},
|
||||
'cpu_times': {'user': 1.0, 'system': 1.0},
|
||||
'io_counters': [0, 0, 0, 0, 0],
|
||||
'time_since_update': 1.0,
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def plugin(glances_stats):
|
||||
"""The shared processlist plugin, fed a fixed list and put back afterwards.
|
||||
|
||||
Building a plugin here instead would write Mock attributes into the glances_processes
|
||||
singleton and break every later test that reads it.
|
||||
"""
|
||||
p = glances_stats.get_plugin('processlist')
|
||||
saved = (p.stats, p.views, getattr(p, '_views_pending', False))
|
||||
p.stats = [make_process(pid) for pid in range(10)]
|
||||
yield p
|
||||
p.stats, p.views, pending = saved
|
||||
p._views_pending = pending
|
||||
|
||||
|
||||
def test_refresh_builds_nothing(plugin):
|
||||
plugin.update_views()
|
||||
assert plugin.views == {}
|
||||
|
||||
|
||||
def test_first_read_builds_the_views(plugin):
|
||||
plugin.update_views()
|
||||
views = plugin.get_views()
|
||||
assert views[4]['cpu_percent']['decoration'] is not None
|
||||
assert len(views) == 10
|
||||
|
||||
|
||||
def test_second_read_reuses_the_built_views(plugin):
|
||||
plugin.update_views()
|
||||
first = plugin.get_views()
|
||||
assert plugin.get_views() is first
|
||||
|
||||
|
||||
def test_json_contains_every_process(plugin):
|
||||
plugin.update_views()
|
||||
assert len(json.loads(plugin.get_json_views())) == 10
|
||||
|
||||
|
||||
def test_reset_stays_reset(plugin):
|
||||
"""Without clearing the pending flag the next read would rebuild what was reset."""
|
||||
plugin.update_views()
|
||||
plugin.reset_views()
|
||||
assert plugin.get_views() == {}
|
||||
|
||||
|
||||
def test_set_views_is_not_overwritten(plugin):
|
||||
plugin.update_views()
|
||||
plugin.set_views({'given': 'by the server'})
|
||||
assert plugin.get_views() == {'given': 'by the server'}
|
||||
Reference in new issue
Block a user