Simpy:如何监控资源使用



我想了解如何收集计算资源使用的数据,例如排队等候的平均客户数量。我看了下面链接的文档,但它对我来说太多了。我正在寻找如何使用它的一个例子,以及如何计算基于时间的平均线长。谢谢你的指导。

https://simpy.readthedocs.io/en/latest/topical_guides/monitoring.html monitoring-your-processes

资源没有使用记录。你需要自己去收集。Monkey补丁是一种用代码包装资源请求以收集统计信息而不改变资源请求调用方式的方法。更简单的方法是创建一个日志记录器,并在需要的地方添加一个日志调用。我在例子中就是这么做的。缺点是你必须记得在需要的时候添加日志代码。

简单资源具有以下属性用于收集统计信息:capacity、count(拥有资源的用户数量)、users(拥有资源的用户列表)、queue(等待的资源请求列表)

"""
A quick example on how to get average line length 
using a custom logger class
programmer: Michael R. Gibbs
"""
import simpy
import numpy as np
import pandas as pd
class LineLogger():
"""
logs the size of a resource line
"""
def __init__(self, env):
self.env = env
# the log
self.samples_df = pd.DataFrame(columns=['time','len'])

def log(self, time, len):
"""
log a time and length of the resoure request queue
time:   time the messure is taken
len:    length of the queue
"""
self.samples_df = self.samples_df.append({'time':time,'len':len},ignore_index=True)
def get_ave_line(self):
"""
finds the time weighted average of the queue length
"""
# use the next row to figure out how long the queue was at that length
self.samples_df['time_span'] = self.samples_df['time'].shift(-1) - self.samples_df['time']
# drop the last row because it would have a infinate time span
trimed_samples_df = self.samples_df[0:-1]
ave = np.average(trimed_samples_df['len'], weights=trimed_samples_df['time_span'])
return ave
def task(env, res, line_logger):
"""
A simple task that grabs a resouce for a bit of time
"""
with res.request() as req:  # Generate a request event
# requester enters queue for resouce
line_logger.log(env.now,len(res.queue))
yield req
# requester got a resource and leaves requeuest queue
# if the resource was available when the request was made, then time in queue will be 0
line_logger.log(env.now,len(res.queue))
# keep resource to build a queue
yield env.timeout(3.5)
def gen_tasks(env, res, line_logger):
"""
generates 5 tasks to seize a resource
building a queue over time
"""
for i in range(5):
env.process(task(env,res,line_logger))
# put some time between requests
yield env.timeout(1)
if __name__ == '__main__':
env = simpy.Environment()
res = simpy.Resource(env, capacity=1)
line_logger = LineLogger(env)
env.process(gen_tasks(env,res,line_logger))
env.run(100)

print("finish sim")
print("average queue length is: ",line_logger.get_ave_line())

print()
print("log data")
print(line_logger.samples_df)
print()
print("done")

使用一个与主进程并行运行的进程来监视利用率。下面是一个生成器函数的样板代码,可以在监视过程中使用。

data = []    
def monitor_process(env, resource):
"""
Generator for monitoring process 
that shares the environment with the main process
and collects information.
"""
while True:
item = (env.now,
resource.count,
len(resource.queue))
data.append(item)
yield env.timeout(0.25)

此生成器函数设置为在每个模拟步骤中轮询资源对象4次,并将结果放入数组中。您可以更改轮询频率。像这样调用这个生成器:

env.process(monitor_process(env, target_resource))

当您调用env.run(until=120)(例如)来运行主进程时,该进程将并行运行并记录资源统计信息。

为了与这种方法进行比较,我已经实现了猴子补丁。monkey - patchching用日志功能装饰资源的一些方法。代码更优雅,但也更复杂。此外,使用猴子补丁,每次事件发生时都会记录资源统计信息,即调用任何目标资源的get、put、request或release方法。我在这里展示的方法将以固定的时间间隔记录资源状态,代码相对更简单。

希望对你有帮助。

干杯!

最新更新