Friday Facts #148 - Optimizations for 0.14
My visit to Prague
Todays Friday Facts are brought to you by Rseding91. I live in the USA and normally work remotely for Wube but I've been visiting Prague for the past 2 months. Since I'm not the touristy kind of person (I'm a programmer) and I love working on Factorio; I've spent almost all of my time here in the office. I've been in Prague since June 6 and my current time sheet says I've logged 568.55 hours.
0.13.0 was released 4 weeks ago and we've had 9 releases since with 280+ bugs fixed of which I've personally fixed 99. We've still got 60+ confirmed bugs to work through however the bug reports are coming in less frequently as time passes. The reported bugs have also changed from "the game crashed, my map is corrupt, my computer exploded" style bugs to this
kind of bug. While yes, it's still a bug, it doesn't break gameplay at all so it's far less critical to get fixed immediately.
The number of repeat bugs (bugs reported, fixed, and then broken again later) is near zero and of the bugs reported and fixed in 0.13 almost all of them where preexisting issues or introduced from features added in 0.13. That means that our automated tests are working and we aren't fighting against ourselves fixing issues we've already fixed.
Other than the outstanding multiplayer issues mentioned in last week's Friday Facts 0.13 is looking great and baring any major bugs we're planning for a stable release August 1st..
0.14 and optimizations
As of now, there hasn't been any concrete plan as to what will go into 0.14. There are still enough bugs to fix that everyone's busy working on those. However, when optimization was mentioned it immediately got my attention and was assigned to myself for 0.14.
Because we put no limits on what you're allowed to build in Factorio and the nature of the game encourages expansion and large factories even the best computers will eventually struggle to keep the game simulation running at the desired 60 updates per second as you expand. So far our main method for addressing slowdown has been "do less". It sounds simple but it rarely is.
A few examples of past performance improvements:
- Transport belts in 0.12 onward only check item collision against the item directly in front of the item being moved. (More in FF #83)
- Solar panels where grouped so regardless of how many you build the calculation is: N * light * power
- Accumulators are grouped similar to solar panels
- Logistic/construction robots don't do any collision checks when moving since they can't ever hit anything anyway
- Most entities will "go to sleep" when they have nothing to do - consuming zero processing time when asleep
Two of the most frequently built entities and subsequently two of the most CPU consuming entities are: transport belts and pipes. The vast majority of them are large section of simple belts without intersections splitters inserters or so. The player simply needed more throughput and so they built 5-10 parallel lines of belts/pipes.
Right now each belt and each pipe is updated individually piece by piece. That means the cost to run those increases as the count of entities does. The other cost is also the transition of fluid/items from each pipe/belt to another.
The belt/pipe lines would be merged and act as series of segments. This allows the items on the segment to be saved in one continuous piece of memory, which not only improves memory locality, but allows us to use tricks to move the items on the belts smarter, instead of moving every item in the segment, we can just change the overall segment offset as long as the belt exit is not blocked. On top of that, the individual belts and pipes wouldn't have to be updated, as their animation can be simply tick-based. In the ideal case, this could improve the performance of transport belts many times!
Again, that sounds simple enough when stated but as I've started to look into what will be required it becomes more and more complex. This is just the initial list of questions that I need to solve before work can really begin on this:
- How is the "other movable" logic meant to be handled for belts and splitters if they aren't going to be updatable
- Right now splitters operate by doing: move items on input lines -> split -> move items on output lines. How will this logic be done when the lines have no knowledge of the splitter or its mechanics?
- Who's responsible for saving transport line data?
- Custom render logic, so the segments draws it items in one go instead of individual items drawing them.
- How is save-load stability going to be maintained for merged transport belts? When a set of belts is merged runtime and then that data is saved how do we ensure the loaded and re-setup belts re-merge in the same way?
- Segment creating/merging/splitting logic. When belts are build/destroyed.
- How will migrations of belts in segment work?
- How will we handle underground belt connection distance changes between save load?
- And many others.
Nothing is ever as simple as you think it should be :)
Between working on bugs and thinking about optimizations in 0.14 I've been working on some smaller features for 0.14. One of them I really like won't change the gameplay but just gives some fun data for multiplayer games: train kills.
As always, let us know what you think on our forums