diff options
author | nicolargo <nicolas@nicolargo.com> | 2021-05-23 18:54:42 +0200 |
---|---|---|
committer | nicolargo <nicolas@nicolargo.com> | 2021-05-23 18:54:42 +0200 |
commit | abb97d5286af5893b2ae69eb7c9c2f1ffc8bf61b (patch) | |
tree | 2affc48ce549204361bdbd008d6384d2414ad570 | |
parent | 0c7e3bca5f2e3cf898f31ed2a0a129dd02159584 (diff) |
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...
-rw-r--r-- | conf/glances.conf | 12 | ||||
-rw-r--r-- | docs/config.rst | 11 | ||||
-rw-r--r-- | glances/__init__.py | 6 | ||||
-rw-r--r-- | glances/main.py | 19 | ||||
-rw-r--r-- | glances/outputs/glances_curses.py | 12 | ||||
-rw-r--r-- | glances/plugins/glances_connections.py | 5 | ||||
-rw-r--r-- | glances/plugins/glances_core.py | 2 | ||||
-rw-r--r-- | glances/plugins/glances_cpu.py | 3 | ||||
-rw-r--r-- | glances/plugins/glances_folders.py | 4 | ||||
-rw-r--r-- | glances/plugins/glances_mem.py | 1 | ||||
-rw-r--r-- | glances/plugins/glances_plugin.py | 33 | ||||
-rw-r--r-- | glances/plugins/glances_ports.py | 18 | ||||
-rw-r--r-- | glances/plugins/glances_processcount.py | 1 | ||||
-rw-r--r-- | glances/processes.py | 9 | ||||
-rw-r--r-- | glances/standalone.py | 3 | ||||
-rw-r--r-- | glances/stats.py | 5 |
16 files changed, 94 insertions, 50 deletions
diff --git a/conf/glances.conf b/conf/glances.conf index 1c24b773..0b04fb34 100644 --- a/conf/glances.conf +++ b/conf/glances.conf @@ -3,6 +3,10 @@ ############################################################################## [global] +# Refresh rate (default is a minimum of 2 seconds) +# Can be overwrite by the -t <sec> option +# It is also possible to overwrite it in each plugin sections +refresh=2 # Does Glances should check if a newer version is available on PyPI ? check_update=false # History size (maximum number of values) @@ -27,6 +31,8 @@ max_processes_display=30 # Set to true to disable a plugin # Note: you can also disable it from the command line (see --disable-plugin <plugin_name>) disable=False +# Set a specific refresh rate for this plugin by overwriting the default/refresh value +#refresh=3 # Graphical percentage char used in the terminal user interface (default is |) percentage_char=| # Define CPU, MEM and SWAP thresholds in % @@ -45,7 +51,7 @@ disable=False # See https://scoutapm.com/blog/slow_server_flow_chart # # I/O wait percentage should be lower than 1/# (# = Logical CPU cores) -# Leave commented to just use the default config: +# Leave commented to just use the default config: # Careful=1/#*100-20% / Warning=1/#*100-10% / Critical=1/#*100 #iowait_careful=30 #iowait_warning=40 @@ -414,8 +420,8 @@ style=DarkStyle [influxdb] # !!! -# Will be DEPRECATED in future release. -# Please have a look on the new influxdb2 export module (compatible with InfluxDB 1.8.x and 2.x) +# Will be DEPRECATED in future release. +# Please have a look on the new influxdb2 export module (compatible with InfluxDB 1.8.x and 2.x) # !!! # Configuration for the --export influxdb option # https://influxdb.com/ diff --git a/docs/config.rst b/docs/config.rst index 07f0efd5..56accc1e 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -39,8 +39,15 @@ A first section (called global) is available: .. code-block:: ini [global] - # Does Glances should check if a newer version is available on PyPI? - check_update=true + # Refresh rate (default is a minimum of 3 seconds) + # Can be overwrite by the -t <sec> option + # It is also possible to overwrite it in each plugin sections + refresh=3 + # Does Glances should check if a newer version is available on PyPI ? + check_update=false + # History size (maximum number of values) + # Default is 28800: 1 day with 1 point every 3 seconds + history_size=28800 Each plugin, export module and application monitoring process (AMP) can have a section. Below an example for the CPU plugin: diff --git a/glances/__init__.py b/glances/__init__.py index 8236a33c..4ef033c5 100644 --- a/glances/__init__.py +++ b/glances/__init__.py @@ -141,9 +141,9 @@ def main(): global core # Create the Glances main instance + # Glances options from the command line are readed first (in __init__) + # then the options from the config file (in parse_args) core = GlancesMain() - config = core.get_config() - args = core.get_args() # Glances can be ran in standalone, client or server mode - start(config=config, args=args) + start(config=core.get_config(), args= core.get_args()) diff --git a/glances/main.py b/glances/main.py index 11e68a3b..77c9471f 100644 --- a/glances/main.py +++ b/glances/main.py @@ -33,8 +33,8 @@ from glances.logger import logger, LOG_FILENAME class GlancesMain(object): """Main class to manage Glances instance.""" - # Default stats' refresh time is 3 seconds - refresh_time = 3 + # Default stats' minimum refresh time is 2 seconds + DEFAULT_REFRESH_TIME = 2 # Set the default cache lifetime to 1 second (only for server) cached_time = 1 # By default, Glances is ran in standalone mode (no client/server) @@ -205,8 +205,8 @@ Examples of use: help='SNMP authentication key (only for SNMPv3)') parser.add_argument('--snmp-force', action='store_true', default=False, dest='snmp_force', help='force SNMP mode') - parser.add_argument('-t', '--time', default=self.refresh_time, type=float, - dest='time', help='set refresh time in seconds [default: {} sec]'.format(self.refresh_time)) + parser.add_argument('-t', '--time', default=self.DEFAULT_REFRESH_TIME, type=float, + dest='time', help='set refresh time in seconds [default: {} sec]'.format(self.DEFAULT_REFRESH_TIME)) parser.add_argument('-w', '--webserver', action='store_true', default=False, dest='webserver', help='run Glances in web server mode (bottle needed)') parser.add_argument('--cached-time', default=self.cached_time, type=int, @@ -258,6 +258,8 @@ Examples of use: args = self.init_args().parse_args() # Load the configuration file, if it exists + # This function should be called after the parse_args + # because the configration file path can be defined self.config = Config(args.conf_file) # Debug mode @@ -268,6 +270,15 @@ Examples of use: from warnings import simplefilter simplefilter("ignore") + # Plugins refresh rate + if self.config.has_section('global'): + global_refresh = self.config.get_float_value('global', + 'refresh', + default=self.DEFAULT_REFRESH_TIME) + if args.time == self.DEFAULT_REFRESH_TIME: + args.time = global_refresh + logger.debug('Global refresh rate is set to {} seconds'.format(args.time)) + # Plugins disable/enable # Allow users to disable plugins from the glances.conf (issue #1378) for s in self.config.sections(): diff --git a/glances/outputs/glances_curses.py b/glances/outputs/glances_curses.py index 2e4a535d..ce4a6e63 100644 --- a/glances/outputs/glances_curses.py +++ b/glances/outputs/glances_curses.py @@ -20,10 +20,9 @@ """Curses interface class.""" from __future__ import unicode_literals -import re import sys -from glances.compat import to_ascii, nativestr, b, u, itervalues, enable, disable +from glances.compat import nativestr, u, itervalues, enable, disable from glances.globals import MACOS, WINDOWS from glances.logger import logger from glances.events import glances_events @@ -104,7 +103,7 @@ class _GlancesCurses(object): # "<" (left arrow) navigation through process sort # ">" (right arrow) navigation through process sort # 'UP' > Up in the server list - # 'DOWN' > Down in the server list + # 'DOWN' > Down in the server list } _sort_loop = ['cpu_percent', 'memory_percent', 'username', @@ -666,9 +665,9 @@ class _GlancesCurses(object): self.args.cursor_position] confirm = self.display_popup( 'Kill process: {} (pid: {}) ?\n\nConfirm ([y]es/[n]o): '.format( - selected_process_raw['name'], - selected_process_raw['pid']), - popup_type='yesno') + selected_process_raw['name'], + selected_process_raw['pid']), + popup_type='yesno') if confirm.lower().startswith('y'): try: ret_kill = glances_processes.kill(selected_process_raw['pid']) @@ -684,7 +683,6 @@ class _GlancesCurses(object): 'Kill process only available in standalone mode') self.kill_process = False - # Display graph generation popup if self.args.generate_graph: self.display_popup('Generate graph in {}'.format(self.args.export_graph_path)) diff --git a/glances/plugins/glances_connections.py b/glances/plugins/glances_connections.py index af727816..16b2239c 100644 --- a/glances/plugins/glances_connections.py +++ b/glances/plugins/glances_connections.py @@ -2,7 +2,7 @@ # # This file is part of Glances. # -# Copyright (C) 2019 Nicolargo <nicolas@nicolargo.com> +# Copyright (C) 2021 Nicolargo <nicolas@nicolargo.com> # # Glances is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by @@ -21,9 +21,8 @@ from __future__ import unicode_literals from glances.logger import logger -from glances.timer import getTimeSinceLastUpdate from glances.plugins.glances_plugin import GlancesPlugin -from glances.compat import n, u, b, nativestr +from glances.compat import nativestr import psutil diff --git a/glances/plugins/glances_core.py b/glances/plugins/glances_core.py index bf1692e0..0e5a9cdc 100644 --- a/glances/plugins/glances_core.py +++ b/glances/plugins/glances_core.py @@ -40,6 +40,8 @@ class Plugin(GlancesPlugin): # The core number is displayed by the load plugin self.display_curse = False + @GlancesPlugin._check_decorator + @GlancesPlugin._log_result_decorator def update(self): """Update core stats. diff --git a/glances/plugins/glances_cpu.py b/glances/plugins/glances_cpu.py index 4ab2ad1a..08cc61e6 100644 --- a/glances/plugins/glances_cpu.py +++ b/glances/plugins/glances_cpu.py @@ -2,7 +2,7 @@ # # This file is part of Glances. # -# Copyright (C) 2019 Nicolargo <nicolas@nicolargo.com> +# Copyright (C) 2021 Nicolargo <nicolas@nicolargo.com> # # Glances is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by @@ -79,7 +79,6 @@ class Plugin(GlancesPlugin): @GlancesPlugin._log_result_decorator def update(self): """Update CPU stats using the input method.""" - # Grab stats into self.stats if self.input_method == 'local': stats = self.update_local() diff --git a/glances/plugins/glances_folders.py b/glances/plugins/glances_folders.py index 49f822dc..8efddadc 100644 --- a/glances/plugins/glances_folders.py +++ b/glances/plugins/glances_folders.py @@ -2,7 +2,7 @@ # # This file is part of Glances. # -# Copyright (C) 2019 Nicolargo <nicolas@nicolargo.com> +# Copyright (C) 2021 Nicolargo <nicolas@nicolargo.com> # # Glances is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by @@ -22,7 +22,7 @@ from __future__ import unicode_literals import numbers -from glances.compat import nativestr, n +from glances.compat import nativestr from glances.folder_list import FolderList as glancesFolderList from glances.plugins.glances_plugin import GlancesPlugin from glances.logger import logger diff --git a/glances/plugins/glances_mem.py b/glances/plugins/glances_mem.py index 33237cc2..417483a3 100644 --- a/glances/plugins/glances_mem.py +++ b/glances/plugins/glances_mem.py @@ -19,6 +19,7 @@ """Virtual memory plugin.""" +from glances.logger import logger from glances.compat import iterkeys from glances.plugins.glances_plugin import GlancesPlugin diff --git a/glances/plugins/glances_plugin.py b/glances/plugins/glances_plugin.py index c6e57950..6e728a10 100644 --- a/glances/plugins/glances_plugin.py +++ b/glances/plugins/glances_plugin.py @@ -34,7 +34,7 @@ from glances.history import GlancesHistory from glances.logger import logger from glances.events import glances_events from glances.thresholds import glances_thresholds -from glances.timer import Counter +from glances.timer import Counter, Timer class GlancesPlugin(object): @@ -104,6 +104,9 @@ class GlancesPlugin(object): self.hide_zero = False self.hide_zero_fields = [] + # Set the initial refresh time to display stats the first time + self.refresh_timer = Timer(0) + # Init the stats self.stats_init_value = stats_init_value self.stats = None @@ -584,6 +587,13 @@ class GlancesPlugin(object): """Set the limits to input_limits.""" self._limits = input_limits + def get_limits(self, item=None): + """Return the limits object.""" + if item is None: + return self._limits + else: + return self._limits.get('{}_{}'.format(self.plugin_name, item), None) + def get_stats_action(self): """Return stats for the action. @@ -989,12 +999,29 @@ class GlancesPlugin(object): ret = '\\' return ret + def get_refresh_time(self): + """Return the plugin refresh time""" + ret = self.get_limits(item='refresh') + if ret is None: + ret = self.args.time + return ret + def _check_decorator(fct): - """Check if the plugin is enabled.""" + """Check decorator for update method. + It checks: + - if the plugin is enabled. + - if the refresh_timer is finished + """ def wrapper(self, *args, **kw): - if self.is_enable(): + if self.is_enable() and self.refresh_timer.finished(): + # Run the method ret = fct(self, *args, **kw) + # Reset the timer + self.refresh_timer.set(self.get_refresh_time()) + self.refresh_timer.reset() else: + # No need to call the method + # Return the last result available ret = self.stats return ret return wrapper diff --git a/glances/plugins/glances_ports.py b/glances/plugins/glances_ports.py index 479801af..cd36dc15 100644 --- a/glances/plugins/glances_ports.py +++ b/glances/plugins/glances_ports.py @@ -2,7 +2,7 @@ # # This file is part of Glances. # -# Copyright (C) 2019 Nicolargo <nicolas@nicolargo.com> +# Copyright (C) 2021 Nicolargo <nicolas@nicolargo.com> # # Glances is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by @@ -60,9 +60,6 @@ class Plugin(GlancesPlugin): self.stats = GlancesPortsList(config=config, args=args).get_ports_list() + \ GlancesWebList(config=config, args=args).get_web_list() - # Init global Timer - self.timer_ports = Timer(0) - # Global Thread running all the scans self._thread = None @@ -73,6 +70,7 @@ class Plugin(GlancesPlugin): # Call the father class super(Plugin, self).exit() + @GlancesPlugin._check_decorator @GlancesPlugin._log_result_decorator def update(self): """Update the ports list.""" @@ -84,15 +82,15 @@ class Plugin(GlancesPlugin): thread_is_running = False else: thread_is_running = self._thread.is_alive() - if self.timer_ports.finished() and not thread_is_running: + if not thread_is_running: # Run ports scanner self._thread = ThreadScanner(self.stats) self._thread.start() - # Restart timer - if len(self.stats) > 0: - self.timer_ports = Timer(self.stats[0]['refresh']) - else: - self.timer_ports = Timer(0) + # # Restart timer + # if len(self.stats) > 0: + # self.timer_ports = Timer(self.stats[0]['refresh']) + # else: + # self.timer_ports = Timer(0) else: # Not available in SNMP mode pass diff --git a/glances/plugins/glances_processcount.py b/glances/plugins/glances_processcount.py index bcc3b219..862d9cd1 100644 --- a/glances/plugins/glances_processcount.py +++ b/glances/plugins/glances_processcount.py @@ -62,6 +62,7 @@ class Plugin(GlancesPlugin): # Note: 'glances_processes' is already init in the glances_processes.py script + @GlancesPlugin._check_decorator @GlancesPlugin._log_result_decorator def update(self): """Update processes stats using the input method.""" diff --git a/glances/processes.py b/glances/processes.py index b7dfe70d..fbecd8d1 100644 --- a/glances/processes.py +++ b/glances/processes.py @@ -2,7 +2,7 @@ # # This file is part of Glances. # -# Copyright (C) 2019 Nicolargo <nicolas@nicolargo.com> +# Copyright (C) 2021 Nicolargo <nicolas@nicolargo.com> # # Glances is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by @@ -17,11 +17,10 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -import operator import os -from glances.compat import iteritems, itervalues, listitems, iterkeys -from glances.globals import BSD, LINUX, MACOS, SUNOS, WINDOWS, WSL +from glances.compat import iterkeys +from glances.globals import BSD, LINUX, MACOS, WINDOWS from glances.timer import Timer, getTimeSinceLastUpdate from glances.filter import GlancesFilter from glances.logger import logger @@ -403,7 +402,7 @@ class GlancesProcesses(object): else: self.auto_sort = auto self._sort_key = key - + def kill(self, pid, timeout=3): """Kill process with pid""" assert pid != os.getpid(), "Glances can kill itself..." diff --git a/glances/standalone.py b/glances/standalone.py index ef255bc4..1e7d070b 100644 --- a/glances/standalone.py +++ b/glances/standalone.py @@ -150,7 +150,8 @@ class GlancesStandalone(object): if not self.quiet: # The update function return True if an exit key 'q' or 'ESC' # has been pressed. - ret = not self.screen.update(self.stats, duration=adapted_refresh) + ret = not self.screen.update(self.stats, + duration=adapted_refresh) else: # Nothing is displayed # Break should be done via a signal (CTRL-C) diff --git a/glances/stats.py b/glances/stats.py index 896eabad..62717005 100644 --- a/glances/stats.py +++ b/glances/stats.py @@ -229,29 +229,24 @@ class GlancesStats(object): # If current plugin is disable # then continue to next plugin continue - start_duration = Counter() # Update the stats... self._plugins[p].update() # ... the history self._plugins[p].update_stats_history() # ... and the views self._plugins[p].update_views() - # logger.debug("Plugin {} update duration: {} seconds".format(p, - # start_duration.get())) def export(self, input_stats=None): """Export all the stats. Each export module is ran in a dedicated thread. """ - # threads = [] input_stats = input_stats or {} for e in self._exports: logger.debug("Export stats using the %s module" % e) thread = threading.Thread(target=self._exports[e].update, args=(input_stats,)) - # threads.append(thread) thread.start() def getAll(self): |