
Load Spreader
A library containing utilities to help spread the load of processing tasks over multiple ticks. This is a dependency for other mods, it does nothing on its own.
Description
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 tickobject_storage(table) - Table containing the objects to processcursors_storage(table) - Storage space for cursor state (should be fromstorage)storage_name(string) - Unique identifier for this cursor in the cursor storagefunc(function) - Function to call for each objectkwargs(table, optional) - Additional arguments to pass tofunc(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 overkey(any|nil) - Current cursor position (nil to start from beginning)
Returns:
next_key(any|nil) - The next key in the table, or nil if emptynext_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 appropria
Ratings & reviews
Sign in to leave a rating or comment.