# Copyright 2020 Modelling, Simulation and Design Lab (MSDL) at
# McGill University and the University of Antwerp (http://msdl.cs.mcgill.ca/)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Makes up a profile of a simulation run.
This file contains the tracer that can analyze the performance and throughput of
the messages traveling through a model during simulation.
"""
from pypdevsbbl.tracers import BaseTracer
[docs]class ProfileTracer(BaseTracer):
"""Traces all the coming and going of messages and transitions.
The output file is in CSV-format and contains two tables, separated with a
newline. For all DEVS blocks that underwent transitions, a summary of the
counts of the internal, external and confluent ones. For all connections, an
overview will be presented of the amount of messages that passed over these
connections. Finally, a total for all values will be given as well.
Args:
uid: A unique identifier for distributed simulation.
Will be set automatically.
server: The server that runs the distributed simulation.
Will be set automatically.
filename (str): The name of the file to write the results to. When
``None``, the console output will be used instead.
"""
def __init__(self, uid, server, filename):
super().__init__(uid, server, filename)
self.connections = {}
self.internal = {}
self.external = {}
self.confluent = {}
[docs] def stopTracer(self):
full = set(self.internal.keys()) | set(self.external.keys()) | set(self.confluent.keys())
self.trace("Name,Internal,External,Confluent\n")
for i in full:
self.trace(i, self.internal.get(i, 0), self.external.get(i, 0), self.confluent.get(i, 0), sep=',', end='\n')
self.trace("TOTAL", sum(self.internal.values()), sum(self.external.values()),
sum(self.confluent.values()), sep=',', end='\n')
self.trace("\nOutport,Inport,Count\n")
for pair in self.connections:
self.trace(*pair, self.connections[pair], sep=',', end='\n')
self.trace("TOTAL", "", sum(self.connections.values()), sep=',', end='\n')
super().stopTracer()
[docs] def traceInternal(self, aDEVS):
name = aDEVS.getModelFullName()
self.internal.setdefault(name, 0)
self.internal[name] += 1
output = aDEVS.my_output
for port in output:
for oport in port.outline:
if oport.type() == 'INPORT':
name = (port.getPortFullName(), oport.getPortFullName())
self.connections.setdefault(name, 0)
self.connections[name] += 1
[docs] def traceExternal(self, aDEVS):
name = aDEVS.getModelFullName()
self.external.setdefault(name, 0)
self.external[name] += 1
[docs] def traceConfluent(self, aDEVS):
name = aDEVS.getModelFullName()
self.confluent.setdefault(name, 0)
self.confluent[name] += 1