Add live profiling results output to rnstatus.
parent
9da6664976
commit
9302415f9e
|
|
@ -190,8 +190,6 @@ class Reticulum:
|
|||
RNS.Transport.exit_handler()
|
||||
RNS.Identity.exit_handler()
|
||||
|
||||
if RNS.Profiler.ran(): RNS.Profiler.results()
|
||||
|
||||
RNS.loglevel = RNS.LOG_NONE
|
||||
RNS._detach_stdout()
|
||||
|
||||
|
|
@ -1293,6 +1291,7 @@ class Reticulum:
|
|||
if path == "packet_rssi": self.rpc_return(conn, self.get_packet_rssi(call["packet_hash"]))
|
||||
if path == "packet_snr": self.rpc_return(conn, self.get_packet_snr(call["packet_hash"]))
|
||||
if path == "packet_q": self.rpc_return(conn, self.get_packet_q(call["packet_hash"]))
|
||||
if path == "profiling_results": self.rpc_return(conn, self.get_profiling_results())
|
||||
if path == "blackholed_identities": self.rpc_return(conn, self.get_blackholed_identities())
|
||||
if path == "is_blackholed": self.rpc_return(conn, self.is_blackholed(call["identity_hash"]))
|
||||
|
||||
|
|
@ -1848,6 +1847,17 @@ class Reticulum:
|
|||
|
||||
return None
|
||||
|
||||
def get_profiling_results(self):
|
||||
if self.is_connected_to_shared_instance:
|
||||
rpc_connection = self.get_rpc_client()
|
||||
rpc_connection.send_bytes(mp.packb({"get": "profiling_results"}))
|
||||
response = mp.unpackb(rpc_connection.recv_bytes())
|
||||
return response
|
||||
|
||||
else:
|
||||
if RNS.Profiler.ran(): return RNS.Profiler.results()
|
||||
else: return None
|
||||
|
||||
def halt_interface(self, interface):
|
||||
pass
|
||||
|
||||
|
|
|
|||
|
|
@ -3339,6 +3339,9 @@ class Transport:
|
|||
response.append(Transport.owner.get_interface_stats())
|
||||
if data[0] == True: response.append(Transport.owner.get_link_count())
|
||||
|
||||
if len(data) >= 2:
|
||||
if data[1] == True: response.append(Transport.owner.get_profiling_results())
|
||||
|
||||
return response
|
||||
|
||||
except Exception as e:
|
||||
|
|
|
|||
|
|
@ -63,9 +63,10 @@ request_concluded = False
|
|||
first_remote_req = True
|
||||
remote_destination = None
|
||||
remote_link = None
|
||||
def get_remote_status(destination_hash, include_lstats, identity, no_output=False, timeout=RNS.Transport.PATH_REQUEST_TIMEOUT):
|
||||
def get_remote_status(destination_hash, include_lstats, include_profiling, identity, no_output=False, timeout=RNS.Transport.PATH_REQUEST_TIMEOUT):
|
||||
global request_result, request_concluded, first_remote_req, remote_destination, remote_link
|
||||
link_count = None
|
||||
profiling_results = None
|
||||
|
||||
if not RNS.Transport.has_path(destination_hash):
|
||||
if not no_output:
|
||||
|
|
@ -114,7 +115,10 @@ def get_remote_status(destination_hash, include_lstats, identity, no_output=Fals
|
|||
if len(response) > 1: link_count = response[1]
|
||||
else: link_count = None
|
||||
|
||||
request_result = (status, link_count)
|
||||
if len(response) > 2: profiling_results = response[2]
|
||||
else: profiling_results = None
|
||||
|
||||
request_result = (status, link_count, profiling_results)
|
||||
|
||||
request_concluded = True
|
||||
|
||||
|
|
@ -125,7 +129,7 @@ def get_remote_status(destination_hash, include_lstats, identity, no_output=Fals
|
|||
print("Sending request...", end=" ")
|
||||
sys.stdout.flush()
|
||||
link.identify(identity)
|
||||
link.request("/status", data = [include_lstats], response_callback = got_response, failed_callback = request_failed)
|
||||
link.request("/status", data = [include_lstats, include_profiling], response_callback = got_response, failed_callback = request_failed)
|
||||
first_remote_req = False
|
||||
|
||||
if not remote_link and not no_output:
|
||||
|
|
@ -155,7 +159,7 @@ def get_remote_status(destination_hash, include_lstats, identity, no_output=Fals
|
|||
def program_setup(configdir, dispall=False, verbosity=0, name_filter=None, json=False, astats=False, pstats=False, lstats=False,
|
||||
sorting=None, sort_reverse=False, remote=None, management_identity=None, must_exit=True, rns_instance=None,
|
||||
traffic_totals=False, discovered_interfaces=False, config_entries=False, burst_filter=False, blocked_ips=False,
|
||||
queue_stats=False, pps=False, remote_timeout=RNS.Transport.PATH_REQUEST_TIMEOUT):
|
||||
queue_stats=False, pps=False, profiling=False, remote_timeout=RNS.Transport.PATH_REQUEST_TIMEOUT):
|
||||
|
||||
if remote: require_shared = False
|
||||
else: require_shared = True
|
||||
|
|
@ -175,6 +179,7 @@ def program_setup(configdir, dispall=False, verbosity=0, name_filter=None, json=
|
|||
link_count = None
|
||||
active_link_count = None
|
||||
stats = None
|
||||
profiling_results = None
|
||||
|
||||
details = False
|
||||
if config_entries:
|
||||
|
|
@ -327,8 +332,8 @@ def program_setup(configdir, dispall=False, verbosity=0, name_filter=None, json=
|
|||
if identity == None: raise ValueError("Could not load management identity from "+str(management_identity))
|
||||
|
||||
try:
|
||||
remote_status = get_remote_status(destination_hash, lstats, identity, no_output=json, timeout=remote_timeout)
|
||||
if remote_status != None: stats, link_count = remote_status
|
||||
remote_status = get_remote_status(destination_hash, lstats, profiling, identity, no_output=json, timeout=remote_timeout)
|
||||
if remote_status != None: stats, link_count, profiling_results = remote_status
|
||||
except Exception as e: raise e
|
||||
|
||||
except Exception as e:
|
||||
|
|
@ -343,6 +348,10 @@ def program_setup(configdir, dispall=False, verbosity=0, name_filter=None, json=
|
|||
try: active_link_count = reticulum.get_active_link_count()
|
||||
except Exception as e: pass
|
||||
|
||||
if profiling:
|
||||
try: profiling_results = reticulum.get_profiling_results()
|
||||
except Exception as e: pass
|
||||
|
||||
try: stats = reticulum.get_interface_stats()
|
||||
except Exception as e: pass
|
||||
|
||||
|
|
@ -799,6 +808,9 @@ def program_setup(configdir, dispall=False, verbosity=0, name_filter=None, json=
|
|||
print(f" {pqpress}")
|
||||
print(f" {ilpress}")
|
||||
|
||||
if profiling_results:
|
||||
print(f"\n Profiling :\n{RNS.Profiler.format_results(profiling_results)}")
|
||||
|
||||
if "transport_id" in stats and stats["transport_id"] != None:
|
||||
print("\n Transport Instance "+RNS.prettyhexrep(stats["transport_id"])+" running")
|
||||
if "network_id" in stats and stats["network_id"] != None:
|
||||
|
|
@ -838,6 +850,7 @@ def main(must_exit=True, rns_instance=None):
|
|||
parser.add_argument("-t", "--totals", action="store_true", help="display traffic totals", default=False)
|
||||
parser.add_argument("-p", "--pps", action="store_true", help="display packets per second in totals", default=False)
|
||||
parser.add_argument("-q", "--queues", action="store_true", help="display queue stats", default=False)
|
||||
parser.add_argument("-z", "--profiling", action="store_true", help="display live profiling results", default=False)
|
||||
parser.add_argument("-s", "--sort", action="store", help="sort interfaces by [rate, traffic, rx, tx, rxs, txs, announces, arx, atx, arxc, atxc, held, prx, ptx, prxc, ptxc, pvs, ivs, flt]", default=None, type=str)
|
||||
parser.add_argument("-r", "--reverse", action="store_true", help="reverse sorting", default=False)
|
||||
parser.add_argument("-j", "--json", action="store_true", help="output in JSON format", default=False)
|
||||
|
|
@ -876,7 +889,7 @@ def main(must_exit=True, rns_instance=None):
|
|||
astats=args.announce_stats, pstats=args.pr_stats, lstats=args.link_stats, sorting=args.sort, sort_reverse=args.reverse,
|
||||
remote=args.R, management_identity=args.i, remote_timeout=args.w, must_exit=False, rns_instance=reticulum,
|
||||
traffic_totals=args.totals, discovered_interfaces=args.discovered, config_entries=args.D, burst_filter=args.burst,
|
||||
blocked_ips=args.blocked_ips, queue_stats=args.queues, pps=args.pps)
|
||||
blocked_ips=args.blocked_ips, queue_stats=args.queues, pps=args.pps, profiling=args.profiling)
|
||||
|
||||
finally:
|
||||
sys.stdout = old_stdout
|
||||
|
|
@ -894,7 +907,7 @@ def main(must_exit=True, rns_instance=None):
|
|||
astats=args.announce_stats, pstats=args.pr_stats, lstats=args.link_stats, sorting=args.sort, sort_reverse=args.reverse,
|
||||
remote=args.R, management_identity=args.i, remote_timeout=args.w, must_exit=must_exit, rns_instance=rns_instance,
|
||||
traffic_totals=args.totals, discovered_interfaces=args.discovered, config_entries=args.D, burst_filter=args.burst,
|
||||
blocked_ips=args.blocked_ips, queue_stats=args.queues, pps=args.pps)
|
||||
blocked_ips=args.blocked_ips, queue_stats=args.queues, pps=args.pps, profiling=args.profiling)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("")
|
||||
|
|
|
|||
|
|
@ -41,21 +41,6 @@ from threading import Lock, Condition
|
|||
|
||||
from ._version import __version__
|
||||
|
||||
from .Reticulum import Reticulum
|
||||
from .Identity import Identity
|
||||
from .Link import Link, RequestReceipt
|
||||
from .Channel import MessageBase
|
||||
from .Buffer import Buffer, RawChannelReader, RawChannelWriter
|
||||
from .Transport import Transport
|
||||
from .Discovery import InterfaceAnnouncer
|
||||
from .Destination import Destination
|
||||
from .Packet import Packet
|
||||
from .Packet import PacketReceipt
|
||||
from .Resolver import Resolver
|
||||
from .Resource import Resource, ResourceAdvertisement
|
||||
from .Cryptography import HKDF
|
||||
from .Cryptography import Hashes
|
||||
|
||||
py_modules = glob.glob(os.path.dirname(__file__)+"/*.py")
|
||||
pyc_modules = glob.glob(os.path.dirname(__file__)+"/*.pyc")
|
||||
modules = py_modules+pyc_modules
|
||||
|
|
@ -492,7 +477,7 @@ class Profiler:
|
|||
from statistics import mean, median, stdev
|
||||
results = {}
|
||||
|
||||
for tag in Profiler.tags:
|
||||
for tag in sorted(Profiler.tags):
|
||||
tag_captures = []
|
||||
tag_entry = Profiler.tags[tag]
|
||||
|
||||
|
|
@ -534,33 +519,41 @@ class Profiler:
|
|||
|
||||
results[tag] = tag_results
|
||||
|
||||
return results
|
||||
|
||||
@staticmethod
|
||||
def format_results(results):
|
||||
def print_results_recursive(tag, results, level=0):
|
||||
print_tag_results(tag, level+1)
|
||||
results_str = print_tag_results(tag, level+1) + "\n"
|
||||
|
||||
for tag_name in results:
|
||||
sub_tag = results[tag_name]
|
||||
if sub_tag["super"] == tag["name"]:
|
||||
print_results_recursive(sub_tag, results, level=level+1)
|
||||
results_str += print_results_recursive(sub_tag, results, level=level+1)
|
||||
|
||||
return results_str
|
||||
|
||||
|
||||
def print_tag_results(tag, level):
|
||||
ind = " "*level
|
||||
name = tag["name"]; count = tag["count"]
|
||||
mean = tag["mean"]; median = tag["median"]; stdev = tag["stdev"]
|
||||
print( f"{ind}{name}")
|
||||
print( f"{ind} Samples : {count}")
|
||||
results_str = f" {ind}{name}\n"
|
||||
results_str += f" {ind} Samples : {count}\n"
|
||||
if stdev != None:
|
||||
print(f"{ind} Mean : {prettyshorttime(mean)}")
|
||||
print(f"{ind} Median : {prettyshorttime(median)}")
|
||||
print(f"{ind} St.dev. : {prettyshorttime(stdev)}")
|
||||
print( f"{ind} Total : {prettyshorttime(mean*count)}")
|
||||
print("")
|
||||
results_str += f" {ind} Mean : {prettyshorttime(mean)}\n"
|
||||
results_str += f" {ind} Median : {prettyshorttime(median)}\n"
|
||||
results_str += f" {ind} St.dev. : {prettyshorttime(stdev)}\n"
|
||||
results_str += f" {ind} Total : {prettyshorttime(mean*count)}\n"
|
||||
return results_str
|
||||
|
||||
print("\nProfiler results:\n")
|
||||
results_str = ""
|
||||
for tag_name in results:
|
||||
tag = results[tag_name]
|
||||
if tag["super"] == None:
|
||||
print_results_recursive(tag, results)
|
||||
results_str += print_results_recursive(tag, results)
|
||||
|
||||
return results_str
|
||||
|
||||
profile = Profiler.get_profiler
|
||||
|
||||
|
|
@ -610,3 +603,20 @@ def bytes_to_b256(data):
|
|||
if not type(data) == bytes: raise TypeError("Invalid input data for base256 encode")
|
||||
try: return [byte_to_b256(c) for c in data]
|
||||
except Exception as e: raise TypeError(f"Could not encode to base256: {e}")
|
||||
|
||||
|
||||
from .Reticulum import Reticulum
|
||||
from .Identity import Identity
|
||||
from .Link import Link, RequestReceipt
|
||||
from .Channel import MessageBase
|
||||
from .Buffer import Buffer, RawChannelReader, RawChannelWriter
|
||||
from .Transport import Transport
|
||||
from .Discovery import InterfaceAnnouncer
|
||||
from .Destination import Destination
|
||||
from .Packet import Packet
|
||||
from .Packet import PacketReceipt
|
||||
from .Resolver import Resolver
|
||||
from .Resource import Resource, ResourceAdvertisement
|
||||
from .Cryptography import HKDF
|
||||
from .Cryptography import Hashes
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue