Skip to content

Optimize particle effects for Folia#206

Merged
Thorinwasher merged 3 commits into
BreweryTeam:masterfrom
MasivoSMP:master
Jun 4, 2026
Merged

Optimize particle effects for Folia#206
Thorinwasher merged 3 commits into
BreweryTeam:masterfrom
MasivoSMP:master

Conversation

@Chesvin1

Copy link
Copy Markdown
Contributor

Hey there!

On Folia, cauldron particles were driven by a global 1-tick task that repeatedly scheduled global tasks for many cauldrons, causing heavy global-thread usage. This change moves particles to per-cauldron Folia region timers. It also switches particle RNG calls to ThreadLocalRandom. Now particle effects stay on the owning region thread and avoid the previous global thread hotspot while preserving behavior.

Here is a Spark report snippet showing the issue:
image
(Ran using canvas's global-tick profiler)

Tested in production already, and I can confirm BreweryX no longer uses any significant % of the global thread

@Thorinwasher Thorinwasher left a comment

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.

It's probably alright, but I often get a bad feel when you allow multiple threads to write to the same field. Wouldn't an alternative optimization be to only run the task (which is used on all other non folia alternatives) on loaded chunks, that would probably help well enough.

private Color particleColor;
private final Location particleLocation;
private final UUID id;
private volatile MyScheduledTask foliaParticleTask;

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.

I started digging a bit into why you would use the volatile keyword here when you're also using the syncronized keyword. I don't think it's necessary as modifying something with a synchronized block also force updates the value for other threads (at least from what it seems like when digging some stuff up)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Hey, sorry for the delay, I kinda forgot about this PR. Anyway, that is right, I guess volatile is redundant here

Comment on lines +435 to +437
if (!config.isEnableCauldronParticles()) {
return;
}

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.

I don't see why you can't just avoid starting the task if it's disabled in the config.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Hmm I’ll clean this up so disabled config doesnt start the task instead of having the repeating task poll that setting

@Chesvin1

Chesvin1 commented Jun 1, 2026

Copy link
Copy Markdown
Contributor Author

It's probably alright, but I often get a bad feel when you allow multiple threads to write to the same field. Wouldn't an alternative optimization be to only run the task (which is used on all other non folia alternatives) on loaded chunks, that would probably help well enough.

Welll, that wouldnt remove the global per-tick scan though. The solution I did is to just avoid that scan altogether and to run it directly in the region scheduler of each cauldron

@Chesvin1 Chesvin1 requested a review from Thorinwasher June 1, 2026 04:59
@Thorinwasher

Thorinwasher commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

I've been without proper internet for 6 days now. Will get back to it when internet is fixed. If I forget, just ping me

@Thorinwasher Thorinwasher merged commit 1dd3a87 into BreweryTeam:master Jun 4, 2026
1 check passed
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.

2 participants