Skip to content

Commit abb97d5

Browse files
committed
First optimzation with a new dynamic way to compute the refresh rate. Good news, the CPU consumption seams to be lower than ~20% with a refresh rate more or less the same...
1 parent 0c7e3bc commit abb97d5

16 files changed

+94
-50
lines changed

conf/glances.conf

+9-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
##############################################################################
44

55
[global]
6+
# Refresh rate (default is a minimum of 2 seconds)
7+
# Can be overwrite by the -t <sec> option
8+
# It is also possible to overwrite it in each plugin sections
9+
refresh=2
610
# Does Glances should check if a newer version is available on PyPI ?
711
check_update=false
812
# History size (maximum number of values)
@@ -27,6 +31,8 @@ max_processes_display=30
2731
# Set to true to disable a plugin
2832
# Note: you can also disable it from the command line (see --disable-plugin <plugin_name>)
2933
disable=False
34+
# Set a specific refresh rate for this plugin by overwriting the default/refresh value
35+
#refresh=3
3036
# Graphical percentage char used in the terminal user interface (default is |)
3137
percentage_char=|
3238
# Define CPU, MEM and SWAP thresholds in %
@@ -45,7 +51,7 @@ disable=False
4551
# See https://scoutapm.com/blog/slow_server_flow_chart
4652
#
4753
# I/O wait percentage should be lower than 1/# (# = Logical CPU cores)
48-
# Leave commented to just use the default config:
54+
# Leave commented to just use the default config:
4955
# Careful=1/#*100-20% / Warning=1/#*100-10% / Critical=1/#*100
5056
#iowait_careful=30
5157
#iowait_warning=40
@@ -414,8 +420,8 @@ style=DarkStyle
414420

415421
[influxdb]
416422
# !!!
417-
# Will be DEPRECATED in future release.
418-
# Please have a look on the new influxdb2 export module (compatible with InfluxDB 1.8.x and 2.x)
423+
# Will be DEPRECATED in future release.
424+
# Please have a look on the new influxdb2 export module (compatible with InfluxDB 1.8.x and 2.x)
419425
# !!!
420426
# Configuration for the --export influxdb option
421427
# https://influxdb.com/

docs/config.rst

+9-2
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,15 @@ A first section (called global) is available:
3939
.. code-block:: ini
4040
4141
[global]
42-
# Does Glances should check if a newer version is available on PyPI?
43-
check_update=true
42+
# Refresh rate (default is a minimum of 3 seconds)
43+
# Can be overwrite by the -t <sec> option
44+
# It is also possible to overwrite it in each plugin sections
45+
refresh=3
46+
# Does Glances should check if a newer version is available on PyPI ?
47+
check_update=false
48+
# History size (maximum number of values)
49+
# Default is 28800: 1 day with 1 point every 3 seconds
50+
history_size=28800
4451
4552
Each plugin, export module and application monitoring process (AMP) can
4653
have a section. Below an example for the CPU plugin:

glances/__init__.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,9 @@ def main():
141141
global core
142142

143143
# Create the Glances main instance
144+
# Glances options from the command line are readed first (in __init__)
145+
# then the options from the config file (in parse_args)
144146
core = GlancesMain()
145-
config = core.get_config()
146-
args = core.get_args()
147147

148148
# Glances can be ran in standalone, client or server mode
149-
start(config=config, args=args)
149+
start(config=core.get_config(), args= core.get_args())

glances/main.py

+15-4
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@
3333
class GlancesMain(object):
3434
"""Main class to manage Glances instance."""
3535

36-
# Default stats' refresh time is 3 seconds
37-
refresh_time = 3
36+
# Default stats' minimum refresh time is 2 seconds
37+
DEFAULT_REFRESH_TIME = 2
3838
# Set the default cache lifetime to 1 second (only for server)
3939
cached_time = 1
4040
# By default, Glances is ran in standalone mode (no client/server)
@@ -205,8 +205,8 @@ def init_args(self):
205205
help='SNMP authentication key (only for SNMPv3)')
206206
parser.add_argument('--snmp-force', action='store_true', default=False,
207207
dest='snmp_force', help='force SNMP mode')
208-
parser.add_argument('-t', '--time', default=self.refresh_time, type=float,
209-
dest='time', help='set refresh time in seconds [default: {} sec]'.format(self.refresh_time))
208+
parser.add_argument('-t', '--time', default=self.DEFAULT_REFRESH_TIME, type=float,
209+
dest='time', help='set refresh time in seconds [default: {} sec]'.format(self.DEFAULT_REFRESH_TIME))
210210
parser.add_argument('-w', '--webserver', action='store_true', default=False,
211211
dest='webserver', help='run Glances in web server mode (bottle needed)')
212212
parser.add_argument('--cached-time', default=self.cached_time, type=int,
@@ -258,6 +258,8 @@ def parse_args(self):
258258
args = self.init_args().parse_args()
259259

260260
# Load the configuration file, if it exists
261+
# This function should be called after the parse_args
262+
# because the configration file path can be defined
261263
self.config = Config(args.conf_file)
262264

263265
# Debug mode
@@ -268,6 +270,15 @@ def parse_args(self):
268270
from warnings import simplefilter
269271
simplefilter("ignore")
270272

273+
# Plugins refresh rate
274+
if self.config.has_section('global'):
275+
global_refresh = self.config.get_float_value('global',
276+
'refresh',
277+
default=self.DEFAULT_REFRESH_TIME)
278+
if args.time == self.DEFAULT_REFRESH_TIME:
279+
args.time = global_refresh
280+
logger.debug('Global refresh rate is set to {} seconds'.format(args.time))
281+
271282
# Plugins disable/enable
272283
# Allow users to disable plugins from the glances.conf (issue #1378)
273284
for s in self.config.sections():

glances/outputs/glances_curses.py

+5-7
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,9 @@
2020
"""Curses interface class."""
2121
from __future__ import unicode_literals
2222

23-
import re
2423
import sys
2524

26-
from glances.compat import to_ascii, nativestr, b, u, itervalues, enable, disable
25+
from glances.compat import nativestr, u, itervalues, enable, disable
2726
from glances.globals import MACOS, WINDOWS
2827
from glances.logger import logger
2928
from glances.events import glances_events
@@ -104,7 +103,7 @@ class _GlancesCurses(object):
104103
# "<" (left arrow) navigation through process sort
105104
# ">" (right arrow) navigation through process sort
106105
# 'UP' > Up in the server list
107-
# 'DOWN' > Down in the server list
106+
# 'DOWN' > Down in the server list
108107
}
109108

110109
_sort_loop = ['cpu_percent', 'memory_percent', 'username',
@@ -666,9 +665,9 @@ def display(self, stats, cs_status=None):
666665
self.args.cursor_position]
667666
confirm = self.display_popup(
668667
'Kill process: {} (pid: {}) ?\n\nConfirm ([y]es/[n]o): '.format(
669-
selected_process_raw['name'],
670-
selected_process_raw['pid']),
671-
popup_type='yesno')
668+
selected_process_raw['name'],
669+
selected_process_raw['pid']),
670+
popup_type='yesno')
672671
if confirm.lower().startswith('y'):
673672
try:
674673
ret_kill = glances_processes.kill(selected_process_raw['pid'])
@@ -684,7 +683,6 @@ def display(self, stats, cs_status=None):
684683
'Kill process only available in standalone mode')
685684
self.kill_process = False
686685

687-
688686
# Display graph generation popup
689687
if self.args.generate_graph:
690688
self.display_popup('Generate graph in {}'.format(self.args.export_graph_path))

glances/plugins/glances_connections.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
# This file is part of Glances.
44
#
5-
# Copyright (C) 2019 Nicolargo <nicolas@nicolargo.com>
5+
# Copyright (C) 2021 Nicolargo <nicolas@nicolargo.com>
66
#
77
# Glances is free software; you can redistribute it and/or modify
88
# it under the terms of the GNU Lesser General Public License as published by
@@ -21,9 +21,8 @@
2121
from __future__ import unicode_literals
2222

2323
from glances.logger import logger
24-
from glances.timer import getTimeSinceLastUpdate
2524
from glances.plugins.glances_plugin import GlancesPlugin
26-
from glances.compat import n, u, b, nativestr
25+
from glances.compat import nativestr
2726

2827
import psutil
2928

glances/plugins/glances_core.py

+2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ def __init__(self, args=None, config=None):
4040
# The core number is displayed by the load plugin
4141
self.display_curse = False
4242

43+
@GlancesPlugin._check_decorator
44+
@GlancesPlugin._log_result_decorator
4345
def update(self):
4446
"""Update core stats.
4547

glances/plugins/glances_cpu.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
# This file is part of Glances.
44
#
5-
# Copyright (C) 2019 Nicolargo <nicolas@nicolargo.com>
5+
# Copyright (C) 2021 Nicolargo <nicolas@nicolargo.com>
66
#
77
# Glances is free software; you can redistribute it and/or modify
88
# it under the terms of the GNU Lesser General Public License as published by
@@ -79,7 +79,6 @@ def __init__(self, args=None, config=None):
7979
@GlancesPlugin._log_result_decorator
8080
def update(self):
8181
"""Update CPU stats using the input method."""
82-
8382
# Grab stats into self.stats
8483
if self.input_method == 'local':
8584
stats = self.update_local()

glances/plugins/glances_folders.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
# This file is part of Glances.
44
#
5-
# Copyright (C) 2019 Nicolargo <nicolas@nicolargo.com>
5+
# Copyright (C) 2021 Nicolargo <nicolas@nicolargo.com>
66
#
77
# Glances is free software; you can redistribute it and/or modify
88
# it under the terms of the GNU Lesser General Public License as published by
@@ -22,7 +22,7 @@
2222

2323
import numbers
2424

25-
from glances.compat import nativestr, n
25+
from glances.compat import nativestr
2626
from glances.folder_list import FolderList as glancesFolderList
2727
from glances.plugins.glances_plugin import GlancesPlugin
2828
from glances.logger import logger

glances/plugins/glances_mem.py

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
"""Virtual memory plugin."""
2121

22+
from glances.logger import logger
2223
from glances.compat import iterkeys
2324
from glances.plugins.glances_plugin import GlancesPlugin
2425

glances/plugins/glances_plugin.py

+30-3
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
from glances.logger import logger
3535
from glances.events import glances_events
3636
from glances.thresholds import glances_thresholds
37-
from glances.timer import Counter
37+
from glances.timer import Counter, Timer
3838

3939

4040
class GlancesPlugin(object):
@@ -104,6 +104,9 @@ def __init__(self,
104104
self.hide_zero = False
105105
self.hide_zero_fields = []
106106

107+
# Set the initial refresh time to display stats the first time
108+
self.refresh_timer = Timer(0)
109+
107110
# Init the stats
108111
self.stats_init_value = stats_init_value
109112
self.stats = None
@@ -584,6 +587,13 @@ def limits(self, input_limits):
584587
"""Set the limits to input_limits."""
585588
self._limits = input_limits
586589

590+
def get_limits(self, item=None):
591+
"""Return the limits object."""
592+
if item is None:
593+
return self._limits
594+
else:
595+
return self._limits.get('{}_{}'.format(self.plugin_name, item), None)
596+
587597
def get_stats_action(self):
588598
"""Return stats for the action.
589599
@@ -989,12 +999,29 @@ def trend_msg(self, trend, significant=1):
989999
ret = '\\'
9901000
return ret
9911001

1002+
def get_refresh_time(self):
1003+
"""Return the plugin refresh time"""
1004+
ret = self.get_limits(item='refresh')
1005+
if ret is None:
1006+
ret = self.args.time
1007+
return ret
1008+
9921009
def _check_decorator(fct):
993-
"""Check if the plugin is enabled."""
1010+
"""Check decorator for update method.
1011+
It checks:
1012+
- if the plugin is enabled.
1013+
- if the refresh_timer is finished
1014+
"""
9941015
def wrapper(self, *args, **kw):
995-
if self.is_enable():
1016+
if self.is_enable() and self.refresh_timer.finished():
1017+
# Run the method
9961018
ret = fct(self, *args, **kw)
1019+
# Reset the timer
1020+
self.refresh_timer.set(self.get_refresh_time())
1021+
self.refresh_timer.reset()
9971022
else:
1023+
# No need to call the method
1024+
# Return the last result available
9981025
ret = self.stats
9991026
return ret
10001027
return wrapper

glances/plugins/glances_ports.py

+8-10
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
# This file is part of Glances.
44
#
5-
# Copyright (C) 2019 Nicolargo <nicolas@nicolargo.com>
5+
# Copyright (C) 2021 Nicolargo <nicolas@nicolargo.com>
66
#
77
# Glances is free software; you can redistribute it and/or modify
88
# it under the terms of the GNU Lesser General Public License as published by
@@ -60,9 +60,6 @@ def __init__(self, args=None, config=None):
6060
self.stats = GlancesPortsList(config=config, args=args).get_ports_list() + \
6161
GlancesWebList(config=config, args=args).get_web_list()
6262

63-
# Init global Timer
64-
self.timer_ports = Timer(0)
65-
6663
# Global Thread running all the scans
6764
self._thread = None
6865

@@ -73,6 +70,7 @@ def exit(self):
7370
# Call the father class
7471
super(Plugin, self).exit()
7572

73+
@GlancesPlugin._check_decorator
7674
@GlancesPlugin._log_result_decorator
7775
def update(self):
7876
"""Update the ports list."""
@@ -84,15 +82,15 @@ def update(self):
8482
thread_is_running = False
8583
else:
8684
thread_is_running = self._thread.is_alive()
87-
if self.timer_ports.finished() and not thread_is_running:
85+
if not thread_is_running:
8886
# Run ports scanner
8987
self._thread = ThreadScanner(self.stats)
9088
self._thread.start()
91-
# Restart timer
92-
if len(self.stats) > 0:
93-
self.timer_ports = Timer(self.stats[0]['refresh'])
94-
else:
95-
self.timer_ports = Timer(0)
89+
# # Restart timer
90+
# if len(self.stats) > 0:
91+
# self.timer_ports = Timer(self.stats[0]['refresh'])
92+
# else:
93+
# self.timer_ports = Timer(0)
9694
else:
9795
# Not available in SNMP mode
9896
pass

glances/plugins/glances_processcount.py

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ def __init__(self, args=None, config=None):
6262

6363
# Note: 'glances_processes' is already init in the glances_processes.py script
6464

65+
@GlancesPlugin._check_decorator
6566
@GlancesPlugin._log_result_decorator
6667
def update(self):
6768
"""Update processes stats using the input method."""

glances/processes.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
# This file is part of Glances.
44
#
5-
# Copyright (C) 2019 Nicolargo <nicolas@nicolargo.com>
5+
# Copyright (C) 2021 Nicolargo <nicolas@nicolargo.com>
66
#
77
# Glances is free software; you can redistribute it and/or modify
88
# it under the terms of the GNU Lesser General Public License as published by
@@ -17,11 +17,10 @@
1717
# You should have received a copy of the GNU Lesser General Public License
1818
# along with this program. If not, see <http://www.gnu.org/licenses/>.
1919

20-
import operator
2120
import os
2221

23-
from glances.compat import iteritems, itervalues, listitems, iterkeys
24-
from glances.globals import BSD, LINUX, MACOS, SUNOS, WINDOWS, WSL
22+
from glances.compat import iterkeys
23+
from glances.globals import BSD, LINUX, MACOS, WINDOWS
2524
from glances.timer import Timer, getTimeSinceLastUpdate
2625
from glances.filter import GlancesFilter
2726
from glances.logger import logger
@@ -403,7 +402,7 @@ def set_sort_key(self, key, auto=True):
403402
else:
404403
self.auto_sort = auto
405404
self._sort_key = key
406-
405+
407406
def kill(self, pid, timeout=3):
408407
"""Kill process with pid"""
409408
assert pid != os.getpid(), "Glances can kill itself..."

glances/standalone.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,8 @@ def __serve_once(self):
150150
if not self.quiet:
151151
# The update function return True if an exit key 'q' or 'ESC'
152152
# has been pressed.
153-
ret = not self.screen.update(self.stats, duration=adapted_refresh)
153+
ret = not self.screen.update(self.stats,
154+
duration=adapted_refresh)
154155
else:
155156
# Nothing is displayed
156157
# Break should be done via a signal (CTRL-C)

0 commit comments

Comments
 (0)