Shared Resources共享资源
在进程交互中可能需要用到,一系列进程进行排队以使用某种资源,比如多个客户等待银行服务,多辆汽车等待通过缴费站,仓库货物的运输消耗和通信网络的数据包转发等.
Resources,可以由有限数量的过程一次使用的进程(例如,具有有限数量的燃油泵的加油站).
Containers,用于模拟同质,无差别主体的生产和消费的资源,可以是连续的(如水)或离散的(如苹果).
Stores,允许生成和使用的Python对象资源.
每个资源有最大容量和两个队列,一个是put something的队列另一个是get something的队列,put()和get()是相应的事件触发的方法.
import simpy
def resource_user(env, resource):
request = resource.request() # Generate a request event
yield request # Wait for access
yield env.timeout(1) # Do something
resource.release(request) # Release the resource
>>> env = simpy.Environment()
>>> res = simpy.Resource(env, capacity=1)#创建资源
>>> user = env.process(resource_user(env, res))
>>> env.run()
因为每次都要release资源,若进程在等待中被中断,则要写成try:…finally:…结构,使用资源的request events能写成
def resource_user(env, resource):
with resource.request() as req: # Generate a request event
yield req # Wait for access
yield env.timeout(1) # Do something
# Resource released automatically
>>> user = env.process(resource_user(env, res))
>>> env.run()
当有多个进程要使用资源时,允许检索当前用户或派对用户的列表,当前用户的数量和资源的容量.
def print_status(res):
res.count, res.capacity, res.users, res.queue
Containers
class GasStation:
def __init__(self, env):
self.fuel_dispensers = simpy.Resource(env, capacity=2)
self.gas_tank = simpy.Container(env, init=100, capacity=1000)
self.mon_proc = env.process(self.monitor_tank(env))
def monitor_tank(self, env):
while True:
if self.gas_tank.level < 100:
print('Calling tanker at %s' % env.now)
env.process(tanker(env, self))
yield env.timeout(15)
def tanker(env, gas_station):
yield env.timeout(10) # Need 10 Minutes to arrive
print('Tanker arriving at %s' % env.now)
amount = gas_station.gas_tank.capacity - gas_station.gas_tank.level
yield gas_station.gas_tank.put(amount)
def car(name, env, gas_station):
print('Car %s arriving at %s' % (name, env.now))
with gas_station.fuel_dispensers.request() as req:
yield req
print('Car %s starts refueling at %s' % (name, env.now))
yield gas_station.gas_tank.get(40)
yield env.timeout(5)
print('Car %s done refueling at %s' % (name, env.now))
def car_generator(env, gas_station):
for i in range(4):
env.process(car(i, env, gas_station))
yield env.timeout(5)
>>> env = simpy.Environment()
>>> gas_station = GasStation(env)
>>> car_gen = env.process(car_generator(env, gas_station))
>>> env.run(35)
Car 0 arriving at 0
Car 0 starts refueling at 0
Car 1 arriving at 5
Car 0 done refueling at 5
Car 1 starts refueling at 5
Car 2 arriving at 10
Car 1 done refueling at 10
Car 2 starts refueling at 10
Calling tanker at 15
Car 3 arriving at 15
Car 3 starts refueling at 15
Tanker arriving at 25
Car 2 done refueling at 30
Car 3 done refueling at 30
Stores
在加油站中,加油机设置为Resource,油罐的油量设为Container,Stores和Container不一样,Stores资源可以是多种多样的就像商店里的各种物品,而Container是同质的单一的无差别主体的,比如油或水.与Store不同,FilterStore可以过滤资源对象,PriorityStore可以设定资源顺序.
def producer(env, store):
for i in range(100):
yield env.timeout(2)
yield store.put('spam %s' % i)
print('Produced spam at', env.now)
def consumer(name, env, store):
while True:
yield env.timeout(1)
print(name, 'requesting spam at', env.now)
item = yield store.get()
print(name, 'got', item, 'at', env.now)
>>> env = simpy.Environment()
>>> store = simpy.Store(env, capacity=2)
>>> prod = env.process(producer(env, store))
>>> consumers = [env.process(consumer(i, env, store)) for i in range(2)]
>>> env.run(until=5)
0 requesting spam at 1
1 requesting spam at 1
Produced spam at 2
0 got spam 0 at 2
0 requesting spam at 3
Produced spam at 4
1 got spam 1 at 4
>>> from collections import namedtuple
>>> Machine = namedtuple('Machine', 'size, duration')
>>> m1 = Machine(1, 2) # Small and slow
>>> m2 = Machine(2, 1) # Big and fast
>>> env = simpy.Environment()
>>> machine_shop = simpy.FilterStore(env, capacity=2)
>>> machine_shop.items = [m1, m2] # Pre-populate the machine shop
def user(name, env, ms, size):
machine = yield ms.get(lambda machine: machine.size == size)
print(name, 'got', machine, 'at', env.now)
yield env.timeout(machine.duration)
yield ms.put(machine)
print(name, 'released', machine, 'at', env.now)
>>> users = [env.process(user(i, env, machine_shop, (i % 2) + 1))
... for i in range(3)]
>>> env.run()
0 got Machine(size=1, duration=2) at 0
1 got Machine(size=2, duration=1) at 0
1 released Machine(size=2, duration=1) at 1
0 released Machine(size=1, duration=2) at 2
2 got Machine(size=1, duration=2) at 2
2 released Machine(size=1, duration=2) at 4
>>> env = simpy.Environment()
>>> issues = simpy.PriorityStore(env)
def inspector(env, issues):
for issue in [simpy.PriorityItem('P2', '#0000'),
simpy.PriorityItem('P0', '#0001'),
simpy.PriorityItem('P3', '#0002'),
simpy.PriorityItem('P1', '#0003')]:
yield env.timeout(1)
print(env.now, 'log', issue)
yield issues.put(issue)
def maintainer(env, issues):
while True:
yield env.timeout(3)
issue = yield issues.get()
print(env.now, 'repair', issue)
>>> _ = env.process(inspector(env, issues))
>>> _ = env.process(maintainer(env, issues))
>>> env.run()
1 log PriorityItem(priority='P2', item='#0000')
2 log PriorityItem(priority='P0', item='#0001')
3 log PriorityItem(priority='P3', item='#0002')
3 repair PriorityItem(priority='P0', item='#0001')
4 log PriorityItem(priority='P1', item='#0003')
6 repair PriorityItem(priority='P1', item='#0003')
9 repair PriorityItem(priority='P2', item='#0000')
12 repair PriorityItem(priority='P3', item='#0002')
Monitoring可以监控process进程,Resource资源使用,跟踪事件模拟.
通信网络仿真包
有人基于python的SimPy包开发了网络仿真包其实就是一个类函数脚本SimComponents,,其相关的详细介绍可转到博客简介.这个仿真平台将各种网络结构抽象成相应的组件,将组件搭建连接起来,就可以完成仿真了,首先介绍网络组件.
Packet
数据包组件,不产生任何动作事件,只是单纯的数据包对象,可以用SimPy的Store资源进行数据包的存取转发,其属性有generation time;size;flow_id;packet id;source;destination.
Packet Generator
数据包生成器产生Packet数据包对象,属性有inter_arrival time;packet size;out成员变量用于将生成器连接到具有put()成员函数的任何组件.
PacketSink
数据接收端组件,记录数据包到达时间和等待时间等信息,支持put()操作.
SwitchPort
交换机端口,在数据交换路由中建立先进先出的队列,可以设置输出端口的速率和队列大小的限制,跟踪收到的数据包和丢弃的数据包.
Portmonitor
端口监视器,监视跟踪交换路由的队列大小.
RandomBrancher
随机分支,解复用元素,按概率随机选择输出端口.
PacketSink.selector
读取数据包的生成源地址,选择符合要求的数据包,进行统计等待时间等信息.
FlowDemux
解复用元素,用于通过flow_id拆分数据包流,具有与构造函数中的概率列表长度相同的输出端口列表,使用这些连接到其它网络元素.
SnoopSplitter
像分离器一样的窥探端口,将原始数据包发送到端口1,并将数据包的副本发送到端口2,设置out1和out的值.
WFQServer
WFQ是Weighted Fair Queuing,加权公平队列,高优先级流量保证带宽,但低优先级流量可以获取公平的贷款共享权力,可以预防高优先级别带宽获取不公平的资源共享.
VirtualClockServer
模拟虚拟时钟服务器