Skip to content

Optimizing the Nuclear Reactor#41

Open
Terkala wants to merge 1 commit intofunky-station:masterfrom
Terkala:Fix-Nuke-Operations
Open

Optimizing the Nuclear Reactor#41
Terkala wants to merge 1 commit intofunky-station:masterfrom
Terkala:Fix-Nuke-Operations

Conversation

@Terkala
Copy link
Contributor

@Terkala Terkala commented Mar 19, 2026

About the PR

Optimized nuclear reactor code so it runs faster.

Why / Balance

The current neutron code is O(N^2) on the number of neutrons. During normal operation that's around 2,000-10,000 operations a second. But at high or near-meltdown temperatures can get over 5 million ops/second. Which massively impacts server performance.

This "should" have no gameplay affect.

Technical details

Removing list.remove and list.add operations from the neutron code, by making it rebuild the neutron list.

Media

Requirements

  • I have read and am following the Pull Request and Changelog Guidelines.
  • I have added media to this PR or it does not require an in-game showcase.
  • If I am porting something, I have done my best to respect the appropriate licenses associated with the presented changes.

License

MIT

Breaking changes

Changelog

🆑 Terkala

  • tweak: Optimized Nuclear Reactor Code for performance

@Terkala
Copy link
Contributor Author

Terkala commented Mar 19, 2026

I strongly recommend AGAINST having the nuclear reactor in forky at all, because of both the massive performance impact and the rather bad gameplay (It can go wrong instantly, with zero feedback as to why, and just blow up in a second. It can blast people with 100+ rads through a wall randomly from across the station.).

But if we're going to have it, it can at least not kill server performance.

@Terkala
Copy link
Contributor Author

Terkala commented Mar 19, 2026

I'm 95% sure this fixes a major slowdown. And about 80% sure this doesn't break anything critical with how the reactor works (I did test it, but just to make sure it emitted neutrons and had them moving around and heating things). I may need to adjust things though.

@jhrushbe
Copy link
Contributor

Intriguing...

Yes, the neutron calculations were something that bothered me because of how large the lists could become in extreme circumstances. That's why I did a bit of my own optimization in RCU8, but if .Remove(T item) is as bad as you say it is then what you've done is better.

Though I do have a question as to the + 16 like in ReactorPartSystem.cs:419, is that to pre-emptively allocate memory for 16 more entries or to make it allocate into the next 2^n block? Also, why 16 in particular?

@Terkala
Copy link
Contributor Author

Terkala commented Mar 20, 2026

It was a bit of a "best guess" to add +16. Since ProcessNeutrons can add more than it removes, and if the list fills up it just fails to add more. So this is a cap on the growth amount so it doesn't experience massive runaway exponential growth. I figured if the emissions can make ~10 neutrons at most, then adding an extra 6 for the ProcessNeutronsGas to add neutrons is reasonable. So the neutrons can't grow more than 16 per-tick. Which is still fast enough, probably?

Downside: No massive instant runaway meltdown
Upside: No massive instant runaway meltdown

@Terkala
Copy link
Contributor Author

Terkala commented Mar 20, 2026

but if .Remove(T item) is as bad as you say it is then what you've done is better.

It ends up doing a linear search to remove that one item. So it's an O(n) operation.

Also I'm only sure that this "still works in the most basic sense" in that I didn't do a lot of testing with this change. I basically just tested that it successfully simulates neutrons, warms up, and has no problem processing them with this code change. So I am a bit worried this might make the behavior very different.

@jhrushbe
Copy link
Contributor

What you're thinking of is an array, not a List.

Lists automatically allocate more memory when it needs more, so there is no way to limit the size of a List with what you've done. Instead, you've just made a list with 16 empty slots where it can fill before it needs to allocate more memory.

As an example of how List (and Dictionary, for that matter) allocation works:

  • A new() list will have a capacity of 1 and a count of 0
  • Using .Add adds the object into the internal array (count: 1)
  • If you use .Add again it will double it's capacity to 2 and then put it into a new slot (count: 2)
  • Using .Add again will double its capacity to 4 (count: 3)
    And so on

Basically, every time it needs more room it will double its capacity

@jhrushbe
Copy link
Contributor

So I am a bit worried this might make the behavior very different.

I've read through your code a few times and can say with a good degree of certainty that the behavior is unchanged, so don't be too worried about that.

@jhrushbe
Copy link
Contributor

In the process of porting it I've done some benchmarks and I must say the time improvements you've made are incredible.

I won't go to far into the details but here's the summary:

  • Old Version: 0.5s process time reached at ~170,000 neutrons
  • New Version: 0.5s process time reached at ~1,150,000 neutrons

Good work.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants