Simpy:如何监控资源使用

问题描述

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

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

解决方法

资源没有利用率日志。您需要自己收集。 Monkey patching 是一种用代码包装资源请求以收集统计信息而不改变资源请求的调用方式的方法。更简单的方法是制作一个记录器,并在需要的地方添加一个日志调用。这就是我在我的例子中所做的。不利的一面是,您必须记住在需要时添加日志记录代码。

简单的资源具有以下收集统计信息的属性:容量、计数(拥有资源的用户数、用户(拥有资源的用户列表)、队列(待处理的资源请求列表)

"""
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,line_logger):
    """
    generates 5 tasks to seize a resource
    building a queue over time
    """

    for i in range(5):
        env.process(task(env,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,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")