Source

circuits / scripts / circuits.bench

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim: set sw=3 sts=3 ts=3

"""(Tool) Bench Marking Tool

THis tool does some simple benchmaking of the circuits library.
"""

import sys
import math
import time
import optparse

try:
    import hotshot
    import hotshot.stats
except ImportError:
    hotshot = None

try:
    import psyco
except ImportError:
    psyco = None

from circuits import __version__ as systemVersion
from circuits import handler, Event, Component, Manager, Debugger

USAGE = "%prog [options]"
VERSION = "%prog v" + systemVersion

###
### Functions
###

def duration(seconds):
    days = int(seconds / 60 / 60 / 24)
    seconds = (seconds) % (60 * 60 * 24)
    hours = int((seconds / 60 / 60))
    seconds = (seconds) % (60 * 60)
    mins = int((seconds / 60))
    seconds = int((seconds) % (60))
    return (days, hours, mins, seconds)

def parse_options():
    """parse_options() -> opts, args

    Parse the command-line options given returning both
    the parsed options and arguments.
    """

    parser = optparse.OptionParser(usage=USAGE, version=VERSION)

    parser.add_option("-t", "--time",
            action="store", type="int", default=0, dest="time",
            help="Stop after specified elapsed seconds")

    parser.add_option("-e", "--events",
            action="store", type="int", default=0, dest="events",
            help="Stop after specified number of events")

    parser.add_option("-p", "--profile",
            action="store_true", default=False, dest="profile",
            help="Enable execution profiling support")

    parser.add_option("-d", "--debug",
            action="store_true", default=False, dest="debug",
            help="Enable debug mode")

    parser.add_option("-m", "--mode",
            action="store", type="choice", default="speed", dest="mode",
            choices=["sync", "speed", "latency"],
            help="Operation mode")

    parser.add_option("-s", "--speed",
            action="store_true", default=False, dest="speed",
            help="Enable psyco (circuits on speed!)")

    parser.add_option("-q", "--quiet",
            action="store_false", default=True, dest="verbose",
            help="Suppress output")

    opts, args = parser.parse_args()

    return opts, args

###
### Events
###

class Stop(Event):
    """Stop Event"""

class Term(Event):
    """Term Event"""

class Hello(Event):
    """Hello Event"""

class Received(Event):
    """Received Event"""

###
### Components
###

class Base(Component):

    def __init__(self, opts, *args, **kwargs):
        super(Base, self).__init__(*args, **kwargs)

        self.opts = opts

class SpeedTest(Base):

    def received(self, message=""):
        self.fire(Hello("hello"))

    def hello(self, message):
        self.fire(Received(message))

class LatencyTest(Base):

    t = None

    def received(self, message=""):
        print("Latency: %0.3f us" % ((time.time() - self.t) * 1e6))
        time.sleep(1)
        self.fire(Hello("hello"))

    def hello(self, message=""):
        self.t = time.time()
        self.fire(Received(message))

class State(Base):

    done = False

    def stop(self):
        self.fire(Term())

    def term(self):
        self.done = True
    
class Monitor(Base):

    sTime = sys.maxsize
    events = 0
    state = 0

    @handler(filter=True)
    def event(self, *args, **kwargs):
        self.events += 1

        if self.events > self.opts.events:
            self.stop()

###
### Main
###

def main():
    opts, args = parse_options()

    if opts.speed and psyco:
        psyco.full()

    manager = Manager()

    monitor = Monitor(opts)
    manager += monitor

    state = State(opts)
    manager += state

    if opts.debug:
        manager += Debugger()

    if opts.mode.lower() == "speed":
        if opts.verbose:
            print("Setting up Speed Test...")
        manager += SpeedTest(opts)
        monitor.sTime = time.time()
    elif opts.mode.lower() == "latency":
        if opts.verbose:
            print("Setting up Latency Test...")
        manager += LatencyTest(opts)
        monitor.sTime = time.time()

    if opts.verbose:
        print("Setting up Sender...")
        print("Setting up Receiver...")

    monitor.sTime = time.time()

    if opts.profile:
        if hotshot:
            profiler = hotshot.Profile("bench.prof")
            profiler.start()

    manager.fire(Hello("hello"))

    while not state.done:
        try:
            manager.tick()

            if opts.events > 0 and monitor.events > opts.events:
                manager.fire(Stop())
            if opts.time > 0 and (time.time() - monitor.sTime) > opts.time:
                manager.fire(Stop())
        except KeyboardInterrupt:
            manager.fire(Stop())

    if opts.verbose:
        print()

    eTime = time.time()

    tTime = eTime - monitor.sTime

    events = monitor.events
    speed = int(math.ceil(float(monitor.events) / tTime))

    print("Total Events: %d (%d/s after %0.2fs)" % (events, speed, tTime))

    if opts.profile and hotshot:
        profiler.stop()
        profiler.close()

        stats = hotshot.stats.load("bench.prof")
        stats.strip_dirs()
        stats.sort_stats("time", "calls")
        stats.print_stats(20)

###
### Entry Point
###

if __name__ == "__main__":
    main()