Skip to content

Caravan Optimizations#567

Open
AFranticTypist wants to merge 16 commits into
pyanodon:masterfrom
AFranticTypist:carvans
Open

Caravan Optimizations#567
AFranticTypist wants to merge 16 commits into
pyanodon:masterfrom
AFranticTypist:carvans

Conversation

@AFranticTypist
Copy link
Copy Markdown
Contributor

Changes:

  • Caravan speed optimizations. Idle caravans are now processed less often, leading to substantial performance improvements in large bases.

  • Minor Caravan schedule UI improvements.

Comment thread scripts/caravan/event-handlers/global.lua Outdated
Comment thread scripts/caravan/impl/actions.lua Outdated
minor simplification
Got rid of CaravanFuncs
Got rid of CaravanFuncs
Got rid of CaravanFuncs
Got rid of CaravanFuncs
@oorzkws
Copy link
Copy Markdown
Contributor

oorzkws commented May 9, 2026

Did you end up solving the difficulties with caravans not waking up after a long idle?

Copy link
Copy Markdown
Contributor

@protocol-1903 protocol-1903 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add as many annotations as possible, I'm trying to get caravans understandible to new readers without having a PHD in spaghetti reading

@AFranticTypist
Copy link
Copy Markdown
Contributor Author

Did you end up solving the difficulties with caravans not waking up after a long idle?

I believe I solved the local issue, but caravans stalling is an entire class of problems that needs a generic "kick after x seconds of inactivity" sort of safety check. It isn't what you should do as these situations should never happen, but problems like this are difficult to catch and debug so it is a practical concession.

@AFranticTypist
Copy link
Copy Markdown
Contributor Author

Please add as many annotations as possible, I'm trying to get caravans understandible to new readers without having a PHD in spaghetti reading

Could you give me more words about what you are looking for here? Maybe point to a good file somewhere?

@protocol-1903
Copy link
Copy Markdown
Contributor

Please add as many annotations as possible, I'm trying to get caravans understandible to new readers without having a PHD in spaghetti reading

Could you give me more words about what you are looking for here? Maybe point to a good file somewhere?

Any files you modified should be annotated, specifically the parts modified by you

@oorzkws
Copy link
Copy Markdown
Contributor

oorzkws commented May 20, 2026

Apologies for the delay on the review, life has been busy. It's still on my list.

@oorzkws
Copy link
Copy Markdown
Contributor

oorzkws commented May 24, 2026

Can you explain storage.caravan_activities to me? Is it just waking the caravan up every 10 actions?

Is there a reason why it can't be part of the caravan_data structure instead, if it's needed?

Copy link
Copy Markdown
Contributor

@oorzkws oorzkws left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation here feels haphazard. I don't want to throw out your work, but I'm wondering the goals (and maintainability) would be better served by using the lessons learned here to plan a clean re-implementation.

Do you know how much of the gains are simply from toggling .active on the idle caravans? The dual queue feels unwieldy, having to count every iteration to decide when to process the slow queue. The same for counting every caravan action for reasons I haven't yet figured out. I feel like we're doing a lot of "work" to avoid processing the queue - which may not take that long.


-- wake up! if it happens to be in deep sleep
if storage.caravans[unit_number].entity ~= nil then
storage.caravans[unit_number].entity.active = true
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the docs: "Writing to this is deprecated and affects only the disabled_by_script state."
disabled_by_script should be written instead

Comment on lines +29 to +30
storage.caravan_fast_queue = nil
storage.caravan_slow_queue = nil
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nilling the table adds needless complexity where we constantly have to check if it exists. We should define the table in on_init/on_configuration_changed and simply leave it empty when we aren't using it

local caravan_data = storage.caravans[tags.unit_number]
local schedule = caravan_data.schedule[tags.schedule_id]

CaravanImpl.wake_up( tags.unit_number )
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a trailing space on this line, along with many others across the PR. It's worth using a linter/formatter with the appropriate settings to prevent this.

I will fix these with a formatting pass when the PR is ready to merge, so don't worry about it for this PR.

if entity.operable then storage.make_operable_next_tick[#storage.make_operable_next_tick + 1] = entity end
entity.operable = false -- Prevents the player from opening the gui of the clicked entity
if entity.name == "outpost" or entity.name == "outpost-fluid" or entity.name == "outpost-aerial" or entity.name == "outpost-aerial-fluid" then
if entity.name == "outpost" or entity.name == "outpost-fluid" or entity.name == "outpost-aerial" then
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merge removed the aerial fluid caravan check here

if not storage.caravan_queue then
local queue = {}
local guis_to_update = {}
local counter = 0
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This variable is unused


-- Under some circumstances caravans can become stuck in wander mode
-- why? don't know. But the solution is to tell them to get back to work.
if not (caravan_data.entity and caravan_data.entity.valid and caravan_data.entity.commandable) then
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In what cases can the commandable be nil?


local cmd = caravan_data.entity.commandable.command

if not (cmd and cmd.type == defines.command.wander) then
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if not cmd or cmd.type ~= defines.command.wander would be more legible

Comment on lines +221 to +223
if not (schedule and schedule.entity and schedule.entity.valid and schedule.entity.surface == caravan_data.entity.surface) then
return false
end
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this work for schedules with a position instead of an entity?

Comment on lines +225 to +226
local action_id = caravan_data.action_id
if action_id < 0 then action_id = 1 end
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the goal here?

Comment thread scripts/caravan/utils.lua
@@ -324,4 +324,5 @@ function P.restore_gui_location(element, fallback_location)
end
end

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this single newline intentionally added?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants