First version of psutil-supported @server command on Windows
This commit is contained in:
parent
5274d111a2
commit
5389373776
1 changed files with 77 additions and 53 deletions
|
|
@ -23,9 +23,8 @@ from evennia.utils.utils import crop
|
|||
from evennia.commands.default.muxcommand import MuxCommand
|
||||
|
||||
# delayed imports
|
||||
_resource = None
|
||||
_idmapper = None
|
||||
_attribute_cache = None
|
||||
_RESOURCE = None
|
||||
_IDMAPPER = None
|
||||
|
||||
# limit symbol import for API
|
||||
__all__ = ("CmdReload", "CmdReset", "CmdShutdown", "CmdPy",
|
||||
|
|
@ -653,52 +652,83 @@ class CmdServerLoad(MuxCommand):
|
|||
def func(self):
|
||||
"Show list."
|
||||
|
||||
caller = self.caller
|
||||
global _IDMAPPER
|
||||
if not _IDMAPPER:
|
||||
from evennia.utils.idmapper import models as _IDMAPPER
|
||||
|
||||
if "flushmem" in self.switches:
|
||||
# flush the cache
|
||||
nflushed = _IDMAPPER.flush_cache()
|
||||
string = "Flushed object idmapper cache. Python garbage " \
|
||||
"collector recovered memory from %i objects."
|
||||
self.caller(string % nflushed)
|
||||
return
|
||||
|
||||
# display active processes
|
||||
|
||||
if not utils.host_os_is('posix'):
|
||||
string = "Process listings are only available under Linux/Unix."
|
||||
caller.msg(string)
|
||||
return
|
||||
|
||||
global _resource, _idmapper
|
||||
if not _resource:
|
||||
import resource as _resource
|
||||
if not _idmapper:
|
||||
from evennia.utils.idmapper import models as _idmapper
|
||||
|
||||
import resource
|
||||
loadavg = os.getloadavg()
|
||||
psize = _resource.getpagesize()
|
||||
os_windows = os.name == "nt"
|
||||
pid = os.getpid()
|
||||
rmem = float(os.popen('ps -p %d -o %s | tail -1' % (pid, "rss")).read()) / 1000.0 # resident memory
|
||||
vmem = float(os.popen('ps -p %d -o %s | tail -1' % (pid, "vsz")).read()) / 1000.0 # virtual memory
|
||||
pmem = float(os.popen('ps -p %d -o %s | tail -1' % (pid, "%mem")).read()) # percent of resident memory to total
|
||||
rusage = resource.getrusage(resource.RUSAGE_SELF)
|
||||
loadtable = EvTable("property", "statistic", align="l")
|
||||
|
||||
if "mem" in self.switches:
|
||||
caller.msg("Memory usage: RMEM: {w%g{n MB (%g%%), VMEM (res+swap+cache): {w%g{n MB." % (rmem, pmem, vmem))
|
||||
return
|
||||
if os_windows:
|
||||
# Windows requires the psutil module to get statistics like this
|
||||
try:
|
||||
import psutil
|
||||
except ImportError:
|
||||
string = "The psutil module is not installed: Process " \
|
||||
" listings are only available under Linux/Unix."
|
||||
self.caller.msg(string)
|
||||
return
|
||||
|
||||
if "flushmem" in self.switches:
|
||||
caller.msg("Flushed object idmapper cache. Python garbage collector recovered memory from %i objects." % _idmapper.flush_cache())
|
||||
return
|
||||
loadavg = psutil.cpu_percent()
|
||||
_mem = psutil.virtual_memory()
|
||||
rmem = _mem.used
|
||||
vmem = "N/A on Windows"
|
||||
pmem = _mem.percent
|
||||
rusage = "N/A on Windows"
|
||||
|
||||
# load table
|
||||
loadtable = prettytable.PrettyTable(["property", "statistic"])
|
||||
loadtable.align = 'l'
|
||||
loadtable.add_row(["Server load (1 min)", "%g" % loadavg[0]])
|
||||
loadtable.add_row(["Process ID", "%g" % pid]),
|
||||
loadtable.add_row(["Bytes per page", "%g " % psize])
|
||||
loadtable.add_row(["CPU time used (total)", "%s (%gs)" % (utils.time_format(rusage.ru_utime), rusage.ru_utime)])
|
||||
loadtable.add_row(["CPU time used (user)", "%s (%gs)" % (utils.time_format(rusage.ru_stime), rusage.ru_stime)])
|
||||
loadtable.add_row(["Memory usage","%g MB (%g%%)" % (rmem, pmem)])
|
||||
loadtable.add_row(["Virtual address space\n {x(resident+swap+caching){n", "%g MB" % vmem])
|
||||
loadtable.add_row(["Page faults", "%g hard, %g soft, %g swapouts" % (rusage.ru_majflt, rusage.ru_minflt, rusage.ru_nswap)])
|
||||
loadtable.add_row(["Disk I/O", "%g reads, %g writes" % (rusage.ru_inblock, rusage.ru_oublock)])
|
||||
loadtable.add_row(["Network I/O", "%g in, %g out" % (rusage.ru_msgrcv, rusage.ru_msgsnd)])
|
||||
loadtable.add_row(["Context switching", "%g vol, %g forced, %g signals" % (rusage.ru_nvcsw, rusage.ru_nivcsw, rusage.ru_nsignals)])
|
||||
if "mem" in self.switches:
|
||||
string = "Memory usage: {w%g{n MB (%g%%)"
|
||||
self.caller.msg(string % (rmem, pmem))
|
||||
return
|
||||
# Display table
|
||||
loadtable.add_row("Server load", "%g" % loadavg)
|
||||
loadtable.add_row("Process ID", "%g" % pid),
|
||||
loadtable.add_row("Memory usage","%g MB (%g%%)" % (rmem, pmem))
|
||||
|
||||
else:
|
||||
# Linux / BSD (OSX)
|
||||
|
||||
global _RESOURCE
|
||||
if not _RESOURCE:
|
||||
import resource as _RESOURCE
|
||||
|
||||
loadavg = os.getloadavg()[0]
|
||||
rmem = float(os.popen('ps -p %d -o %s | tail -1' % (pid, "rss")).read()) / 1000.0 # resident memory
|
||||
vmem = float(os.popen('ps -p %d -o %s | tail -1' % (pid, "vsz")).read()) / 1000.0 # virtual memory
|
||||
pmem = float(os.popen('ps -p %d -o %s | tail -1' % (pid, "%mem")).read()) # percent of resident memory to total
|
||||
rusage = _RESOURCE.getrusage(_RESOURCE.RUSAGE_SELF)
|
||||
|
||||
if "mem" in self.switches:
|
||||
string = "Memory usage: RMEM: {w%g{n MB (%g%%), " \
|
||||
" VMEM (res+swap+cache): {w%g{n MB."
|
||||
self.caller.msg(string % (rmem, pmem, vmem))
|
||||
return
|
||||
|
||||
loadtable.add_row("Server load (1 min)", "%g" % loadavg)
|
||||
loadtable.add_row("Process ID", "%g" % pid),
|
||||
loadtable.add_row("Memory usage","%g MB (%g%%)" % (rmem, pmem))
|
||||
loadtable.add_row("Virtual address space", "")
|
||||
loadtable.add_row("{x(resident+swap+caching){n", "%g MB" % vmem)
|
||||
loadtable.add_row("CPU time used (total)", "%s (%gs)" % (utils.time_format(rusage.ru_utime), rusage.ru_utime))
|
||||
loadtable.add_row("CPU time used (user)", "%s (%gs)" % (utils.time_format(rusage.ru_stime), rusage.ru_stime))
|
||||
loadtable.add_row("Page faults", "%g hard, %g soft, %g swapouts" % (rusage.ru_majflt, rusage.ru_minflt, rusage.ru_nswap))
|
||||
loadtable.add_row("Disk I/O", "%g reads, %g writes" % (rusage.ru_inblock, rusage.ru_oublock))
|
||||
loadtable.add_row("Network I/O", "%g in, %g out" % (rusage.ru_msgrcv, rusage.ru_msgsnd))
|
||||
loadtable.add_row("Context switching", "%g vol, %g forced, %g signals" % (rusage.ru_nvcsw, rusage.ru_nivcsw, rusage.ru_nsignals))
|
||||
|
||||
|
||||
# os-generic
|
||||
|
||||
string = "{wServer CPU and Memory load:{n\n%s" % loadtable
|
||||
|
||||
|
|
@ -707,20 +737,14 @@ class CmdServerLoad(MuxCommand):
|
|||
# because it lacks sys.getsizeof
|
||||
|
||||
# object cache size
|
||||
total_num, cachedict = _idmapper.cache_size()
|
||||
total_num, cachedict = _IDMAPPER.cache_size()
|
||||
sorted_cache = sorted([(key, num) for key, num in cachedict.items() if num > 0],
|
||||
key=lambda tup: tup[1], reverse=True)
|
||||
memtable = prettytable.PrettyTable(["entity name",
|
||||
"number",
|
||||
"idmapper %%"])
|
||||
memtable.align = 'l'
|
||||
memtable = EvTable("entity name", "number", "idmapper %%", align="l")
|
||||
for tup in sorted_cache:
|
||||
memtable.add_row([tup[0],
|
||||
"%i" % tup[1],
|
||||
"%.2f" % (float(tup[1]) / total_num * 100)])
|
||||
memtable.add_row(tup[0], "%i" % tup[1], "%.2f" % (float(tup[1]) / total_num * 100))
|
||||
|
||||
# get sizes of other caches
|
||||
string += "\n{w Entity idmapper cache:{n %i items\n%s" % (total_num, memtable)
|
||||
|
||||
caller.msg(string)
|
||||
|
||||
# return to caller
|
||||
self.caller.msg(string)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue