Exemplo n.º 1
0
def test_scaled_multiple():
    sch = sched.scaled_scheduler(timer, sleep)
    beg = timer()
    dur = 15.0
    lat =  0.10
    log = [] # [(timeout, 'name', priority, delay, latency), ...]

    # Schedule a bunch of events, for immediate execution at the same
    # instant, and 0.0 delay on reschedule.  This will force the scheduler
    # to select them based on priority scaling of their age
    mix = [ 
        ('a  -1/2', 0.50),
        ('b 1-'   , 1),
        ('c 1-1/4', 1.25),
        ('d 2-',    2.00),
        ('e 1-',    1.00),
        ('f 1-1/2', 1.50),
        ('g 0-1/4', 0.25),
        ('h 3-1/4', 3.25),
        ('i  -1/8', 0.125),
        ]
    for name, prio in mix:
        sch.enterabs(beg, prio,
                     reschedule, (log, beg + dur, sch, name, prio, 0.0, lat),
                     kwargs={'event_time':beg})
    siz = len(sch.queue)
    
    sch.run()

    # Given a certain function latency 'lat', and a total duration of
    # 'dur', we can compute roughly how many times reschedule should have
    # triggered...  Of course, 
    print( "\ntime  name  overdue" )
    for expiry, name, prio, delay, lat, overdue in log:
        print( "%7.3f %-10s %7.3fs" % (expiry - beg, name, overdue) )
    runs = len(log); assert dur/lat * .9 < runs-siz < dur/lat * 1.1

    # Count up the incidence of each type of event, and make sure their
    # distribution reflects their relative priority.
    prio_sum = 0.
    for name, prio in mix:
        prio_sum += prio
    ovr = {}
    rel = {}
    for now, name, prio, delay, latency, overdue in log:
        try:    rel[name] += 1
        except: rel[name]  = 1
        try:    ovr[name] += overdue
        except: ovr[name]  = overdue
    for name, prio in mix:
        strength = prio / prio_sum
        incidence = rel[name] / len(log)
        error = (incidence - strength) / strength
        overdue = ovr[name]/rel[name]  # Average overdue in seconds
        print( "%3d x %-10s prio == %7f; %4.2fs overdue; strengh == % 5.1f%% vs. % 5.1f%% incidence (% 5.1f%% err.)" % (
            rel[name], name, prio, overdue, strength*100, incidence*100, error*100))
        # Within 5 percentage points of where they should be...  This is a very loose metric,
        # because (especially for very low priority events), even one extra scheduling out of 100
        # may result in a very high error "percentage".
        assert abs(incidence - strength) < .05
Exemplo n.º 2
0
def test_scaled_basic():
    sch = sched.scaled_scheduler(timer, sleep)
    beg = timer()
    when = []
    sch.enter( 1.0, 0, lambda: when.append(timer()), () )
    sch.run()
    now = timer()
    elapsed = now - beg;     assert 0.90 < elapsed < 1.10	# Total run should take ~1 second
    delayed =when[0] - beg;  assert 0.90 < delayed < 1.10
Exemplo n.º 3
0
def test_scaled_cancellation():
    sch = sched.scaled_scheduler(timer, sleep)
    beg = timer()
    when = []
    e = sch.enterabs( beg + 2.0, 0, lambda: when.append(timer()), () )
    threading.Timer( 0.5, lambda: sch.cancel(e)).start()
    sch.run()
    now = timer()
    elapsed = now - beg;     assert 0.40 < elapsed < 0.60	# Total run should take ~1/2 second
    assert len(when) == 0					# And no events should fire
Exemplo n.º 4
0
def test_scaled_preemption():
    sch = sched.scaled_scheduler(timer, sleep)
    beg = timer()
    when = []
    sch.enterabs( beg + 2.0, 0, lambda: when.append(timer()), () )
    threading.Timer( 0.5, lambda: sch.enterabs( beg + 1.0, 0, lambda: when.append(timer()), () )).start()
    sch.run()
    now = timer()
    elapsed = now - beg;     assert 1.90 < elapsed < 2.10	# Total run should take ~2 seconds
    delay00 = when[0] - beg; assert 0.90 < delay00 < 1.10	# The Timer-scheduled event, now 1s ago
    delay01 = when[1] - beg; assert 1.90 < delay01 < 2.10	# The original event, just expired
Exemplo n.º 5
0
def test_scaled_cancellation():
    sch = sched.scaled_scheduler(timer, sleep)
    beg = timer()
    when = []
    e = sch.enterabs(beg + 2.0, 0, lambda: when.append(timer()), ())
    threading.Timer(0.5, lambda: sch.cancel(e)).start()
    sch.run()
    now = timer()
    elapsed = now - beg
    assert 0.40 < elapsed < 0.60  # Total run should take ~1/2 second
    assert len(when) == 0  # And no events should fire
Exemplo n.º 6
0
def test_scaled_basic():
    sch = sched.scaled_scheduler(timer, sleep)
    beg = timer()
    when = []
    sch.enter(1.0, 0, lambda: when.append(timer()), ())
    sch.run()
    now = timer()
    elapsed = now - beg
    assert 0.90 < elapsed < 1.10  # Total run should take ~1 second
    delayed = when[0] - beg
    assert 0.90 < delayed < 1.10
Exemplo n.º 7
0
def test_scaled_preemption():
    sch = sched.scaled_scheduler(timer, sleep)
    beg = timer()
    when = []
    sch.enterabs(beg + 2.0, 0, lambda: when.append(timer()), ())
    threading.Timer(
        0.5, lambda: sch.enterabs(beg + 1.0, 0, lambda: when.append(timer()),
                                  ())).start()
    sch.run()
    now = timer()
    elapsed = now - beg
    assert 1.90 < elapsed < 2.10  # Total run should take ~2 seconds
    delay00 = when[0] - beg
    assert 0.90 < delay00 < 1.10  # The Timer-scheduled event, now 1s ago
    delay01 = when[1] - beg
    assert 1.90 < delay01 < 2.10  # The original event, just expired
Exemplo n.º 8
0
def test_scaled_multiple():
    sch = sched.scaled_scheduler(timer, sleep)
    beg = timer()
    dur = 15.0
    lat = 0.10
    log = []  # [(timeout, 'name', priority, delay, latency), ...]

    # Schedule a bunch of events, for immediate execution at the same
    # instant, and 0.0 delay on reschedule.  This will force the scheduler
    # to select them based on priority scaling of their age
    mix = [
        ('a  -1/2', 0.50),
        ('b 1-', 1),
        ('c 1-1/4', 1.25),
        ('d 2-', 2.00),
        ('e 1-', 1.00),
        ('f 1-1/2', 1.50),
        ('g 0-1/4', 0.25),
        ('h 3-1/4', 3.25),
        ('i  -1/8', 0.125),
    ]
    for name, prio in mix:
        sch.enterabs(beg,
                     prio,
                     reschedule, (log, beg + dur, sch, name, prio, 0.0, lat),
                     kwargs={'event_time': beg})
    siz = len(sch.queue)

    sch.run()

    # Given a certain function latency 'lat', and a total duration of
    # 'dur', we can compute roughly how many times reschedule should have
    # triggered...  Of course,
    print("\ntime  name  overdue")
    for expiry, name, prio, delay, lat, overdue in log:
        print("%7.3f %-10s %7.3fs" % (expiry - beg, name, overdue))
    runs = len(log)
    assert dur / lat * .9 < runs - siz < dur / lat * 1.1

    # Count up the incidence of each type of event, and make sure their
    # distribution reflects their relative priority.
    prio_sum = 0.
    for name, prio in mix:
        prio_sum += prio
    ovr = {}
    rel = {}
    for now, name, prio, delay, latency, overdue in log:
        try:
            rel[name] += 1
        except:
            rel[name] = 1
        try:
            ovr[name] += overdue
        except:
            ovr[name] = overdue
    for name, prio in mix:
        strength = prio / prio_sum
        incidence = rel[name] / len(log)
        error = (incidence - strength) / strength
        overdue = ovr[name] / rel[name]  # Average overdue in seconds
        print(
            "%3d x %-10s prio == %7f; %4.2fs overdue; strengh == % 5.1f%% vs. % 5.1f%% incidence (% 5.1f%% err.)"
            % (rel[name], name, prio, overdue, strength * 100, incidence * 100,
               error * 100))
        # Within 5 percentage points of where they should be...  This is a very loose metric,
        # because (especially for very low priority events), even one extra scheduling out of 100
        # may result in a very high error "percentage".
        assert abs(incidence - strength) < .05