Exemplo n.º 1
0
    def __init__(self, recorder):
        """ Initialize the monitoring class.

        Parameters
        ----------
        recorder : object
            A subclass of :class:`~pikos.recorders.AbstractRecorder` or a class
            that implements the same interface to handle the values to be
            recorded.

        """
        self._recorder = recorder
        self._tracer = TraceFunctions()
        self._index = 0
        self._call_tracker = KeepTrack()
Exemplo n.º 2
0
class LineMemoryMonitor(object):
    """ Record process memory on python function events.

    The class hooks on the settrace function to receive trace events and
    record the current process memory when a line of code is about to be
    executed.

    Private
    -------
    _recorder : object
        A recorder object that implementes the
        :class:`~pikos.recorder.AbstractRecorder` interface.

    _tracer : object
        An instance of the
        :class:`~pikos._internal.trace_functions.TraceFunctions` utility
        class that is used to set and unset the settrace function as required
        by the monitor.

    _index : int
        The current zero based record index. Each function event will increase
        the index by one.

    _call_tracker : object
        An instance of the :class:`~pikos._internal.keep_track` utility class
        to keep track of recursive calls to the monitor's :meth:`__enter__` and
        :meth:`__exit__` methods.

    _process : object
       An instanse of :class:`psutil.Process` for the current process, used to
       get memory information in a platform independent way.

    """

    def __init__(self, recorder):
        """ Initialize the monitoring class.

        Parameters
        ----------
        recorder : object
            A subclass of :class:`~pikos.recorders.AbstractRecorder` or a class
            that implements the same interface to handle the values to be
            recorded.

        """
        self._recorder = recorder
        self._tracer = TraceFunctions()
        self._index = 0
        self._call_tracker = KeepTrack()
        self._process = None

    def __enter__(self):
        """ Enter the monitor context.

        The first time the method is called (the context is entered) it will
        initialze the Process class, set the settrace hook and initialize the
        recorder.

        """
        if self._call_tracker('ping'):
            self._process = psutil.Process(os.getpid())
            self._recorder.prepare(LineMemoryRecord)
            self._tracer.set(self.on_line_event)

    def __exit__(self, exc_type, exc_val, exc_tb):
        """ Exit the monitor context.

        The last time the method is called (the context is exited) it will
        unset the settrace hook, finalize the recorder and set
        :attr:`_process` to None.

        """
        if self._call_tracker('pong'):
            self._tracer.unset()
            self._recorder.finalize()

    def on_line_event(self, frame, why, arg):
        """ Record the current line trace event.

        Called on trace events and when they refer to line traces, it will
        retrieve the necessary information from the `frame` and get the
        current memory info, create a :class:`LineMemoryRecord` and send it to
        the recorder.

        """
        if why.startswith('l'):
            usage = self._process.get_memory_info()
            filename, lineno, function, line, _ = \
                inspect.getframeinfo(frame, context=1)
            if line is None:
                line = ['<compiled string>']
            record = LineMemoryRecord(self._index, function, lineno, usage.rss,
                                      usage.vms, line[0], filename)
            self._recorder.record(record)
            self._index += 1
        return self.on_line_event