Load Spreader
A Factorio library mod that provides utilities to spread processing tasks over multiple ticks, helping to maintain game performance when working with large datasets.
Table of Contents
- Overview
- Installation
- As a Dependency
- Usage in Your Mod
- API Reference
load_spreader.process_up_to_limit()utilities.select_next_item()- Use Cases
- How It Works
- Requirements
- Support
- Credits
- License
Overview
Load Spreader allows mod developers to process large collections of objects incrementally across multiple game ticks instead of processing everything in a single tick. This prevents UPS drops and maintains smooth gameplay even when dealing with thousands of entities or complex calculations.
Installation
As a Dependency
Add Load Spreader as a dependency in your mod's info.json:
{
"dependencies": ["base >= 2.0", "load-spreader >= 1.0.0"]
}
Usage in Your Mod
Require the library in your mod:
local load_spreader = require("__load-spreader__/load_spreader")
local utilities = require("__load-spreader__/utilities")
API Reference
load_spreader.process_up_to_limit()
Iterates up to a specified limit on a table, passing each object to a processing function. This allows you to control how many items are processed per tick.
Parameters:
- limit (integer) - Maximum number of items to process this tick
- object_storage (table) - Table containing the objects to process
- cursors_storage (table) - Storage space for cursor state (should be from storage)
- storage_name (string) - Unique identifier for this cursor in the cursor storage
- func (function) - Function to call for each object
- kwargs (table, optional) - Additional arguments to pass to func (Note: "object" and "key" are reserved)
Example:
-- In control.lua
local load_spreader = require("__load-spreader__/load_spreader")
-- Initialize storage
script.on_init(function()
storage.my_entities = {}
storage.cursors = {}
end)
-- Process entities
local function make_entity_operable(kwargs)
local entity = kwargs.object
local key = kwargs.key
local bonus_param = kwargs.bonus_param
-- Your processing logic here
if entity.valid then
-- Obviously, this is only an exemple, I expect you to use this
-- to do more complex stuff, like operations on inventories and such.
entity.operable(kwargs.is_operable)
else
storage.my_entities[key] = nil
end
end
script.on_event(defines.events.on_tick, function()
-- Process up to 50 entities per tick
load_spreader.process_up_to_limit(
50, -- limit
storage.my_entities, -- object_storage
storage.cursors, -- cursors_storage
"entity_processor", -- storage_name
make_entity_operable, -- func
{["is_operable"] = true} -- kwargs (optional)
)
end)
utilities.select_next_item()
Safely iterates to the next item in a table with stateful iteration and automatic wrap-around.
Parameters:
- tbl (table) - The table to iterate over
- key (any|nil) - Current cursor position (nil to start from beginning)
Returns:
- next_key (any|nil) - The next key in the table, or nil if empty
- next_value (any|nil) - The value associated with next_key, or nil if empty
Example:
local utilities = require("__load-spreader__/utilities")
local my_table = {a = 1, b = 2, c = 3}
local cursor = nil
-- First call
local cursor, value = utilities.select_next_item(my_table, cursor) -- Returns first item
-- Subsequent calls
local cursor, value = utilities.select_next_item(my_table, cursor) -- Next item
-- When reaching the end, automatically wraps to the beginning
Use Cases
- Processing large entity lists: Spread entity updates across multiple ticks
- Complex calculations: Break up expensive operations into manageable chunks
- Periodic maintenance: Check and update game state without causing lag spikes
- Platform logistics: Evaluate platform requests incrementally (as used in Inter Platform Logistics)
How It Works
Load Spreader uses a cursor system to remember where processing stopped in the previous tick. When called again, it resumes from that position and processes up to the specified limit. Once it reaches the end of the table, the cursor automatically wraps around to the beginning, creating a continuous processing cycle.
This ensures:
- Even distribution of processing load across ticks
- No items are skipped or processed twice consecutively
- Graceful handling of table modifications during iteration
Requirements
- Factorio 2.0 or higher
- Base mod >= 2.0.69
Support
- Discord: puke0417
- Community: Join our Discord
Credits
Author: SirPuck
License
This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
You are free to:
- Share — copy and redistribute the material in any medium or format
- Adapt — remix, transform, and build upon the material
Under the following terms:
- Attribution — You must give appropriate credit to SirPuck, provide a link to the license, and indicate if changes were made
- NonCommercial — You may not use the material for commercial purposes
- ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license
Load Spreader was developed to handle performance optimization needs in Inter Platform Logistics and is provided as a general-purpose library for the Factorio modding community.