Skip to content

Boltzman performance issue #2224

@quaquel

Description

@quaquel

In mesa-frames, there has been a bit of discussion on the performance of the Boltzman Wealth model. I have investigated the issue and conclude that the problem is not with the AgentSet as used in the scheduler. Instead, the problem stems from how a user can access all agents in the model.

Below, we see the performance of 3 versions of the model. Original is the current example version of the model. List is a version of the model where the scheduler is replaced with a list, and in the Agent, this list is also used to select another agent with whom to swap wealth. Test is an intermediate version. The model uses a regular scheduler but the Agent uses the list.

Below are the key code snippets

# original
other_agent = self.random.choice(self.model.schedule.agents)

# test & list
other_agent = self.random.choice(self.model.my_agents)

# in MoneyModel for test and list

self.my_agents = []

# Create agents
for i in range(self.num_agents):
    a = MoneyAgent(i, self)

    # Add the agent to the scheduler for test
    self.schedule.add(a)
    
    self.my_agents.append(a)

readme_plot

As seen in the first plot, the original version scales poorly, but list and test seem very similar. So, below, we compare these in more detail up to 10k agents. As can be seen, using a list within the Agent solves virtually all performance loss. The small remaining difference in performance is the overhead of using AgentSet inside the scheduler instead of using a simple list. This is entirely due to the reliance on weak references in AgentSet.

readme_plot3

So what does this mean? The way in which a user can get hold of all agents in the model needs to be refined. Currently, the model has a dictionary with classes as keys, and lists with hard references as values. Every time you do model.agents this is copied into a new AgentSet class. This creates a lot of overhead. For Mesa 3, I suggest having both a list with the hard references and actively maintaining an AgentSet with all agents. Model.agents can then always return this AgentSet, while the list with hard references can be a private attribute on the model.

I also want to know if we need to maintain the dict with Agent classes as key and lists of agents as values. With AgentSet.groupby, this is redundant unless a user needs frequent and fast access to agents by class and the agents in the model change a lot from one tick to the next.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions