TeamPneumatic / pnc-repressurized

A port of PneumaticCraft to MC1.12+
Other
122 stars 48 forks source link

[Discussion] Drone Programming Best Practices #446

Open MuteTiefling opened 4 years ago

MuteTiefling commented 4 years ago

I've been spending a lot of time programming drones since Covid-19 started and I keep running into walls with performance. I'm certain that's both a combination of what I'm doing and the limitations of my own computer and not necessarily anything wrong with PNC, but still, I'm wondering if there are any recommendations of things to do or avoid.

For instance, I recently built a program that would go and check how many ingots are in a chest. If it was below a certain threshold, the drone would go pick up the corresponding ore and smelt it. Then it would pick up the results and store it in the chest. This mostly worked but I had trouble with the timing element, so I broke it into two programs on Network APIs and started running them with a Remote Program drone instead. Seemed to be good and each would control the other (Smelting would trigger a global boolean and the collect would only run if that was true, similarly the smelting program wouldn't run again until the collection had completed)

Fast forward six more ingot types and 12 more programs dealing with them all, one for smelting, one for retrieval. The drone would scan the chest for these 14 programs, each which started off with that simple inventory condition and exited if no action was necessary. Then I'd go to a 30 second wait program before looping through all of the programs again. At this point, my system started to struggle and the logs were getting spammed with the dreaded Could Not Keep Up message.

It seems like that rapid fire inventory check every 30 seconds was at the heart of the performance drop. So would it be better to have a wait between each of them? Or should I have a programmable controller doing a less frequent check and storing the results in global variables for the drone to check instead? Are remote programs themselves a cause for concern by having too many in the same inventory?

Eventually my goal is to have drones that keep a certain stockpile of basic parts ready for me at all times, including smelting ores, making alloys, plates, gears, wires, machine frames, etc. Effectively the most used crafting components I have. So I'd be doing an enormous amount of inventory checks when it's all done. I know from experience with other mods that these seem to be rather heavy for minecraft to process (I've killed my game before by doing too many Botania Corporea requests too quickly, for instance). That's why I figured I should put the wait sequences in there but it doesn't seem to be enough.

desht commented 4 years ago

Hmm, this is something I will need to do some testing with. I can't see anything obviously wrong with what you're doing offhand, but it's possible that loading 14 programs like that in a row could be trigger a problem (e.g. forcing recaching of the drone's areas would be an expensive operation and likely to cause lag). But that's speculation at this point - I'll need to do some investigation to see if I can spot any issues...

Tekstack commented 4 years ago

@desht glad to see that you've been hard at it as always (been about a year since playing, Covid has given me some extra time, about to hop back in :P ) Also, if you could check the below for accuracy, as for what I said earlier, it's been many moons since I've played.

@MuteTiefling I have been out of game for about a year (so apologies if some of the information from my experiences don't apply now). As far as optimizing drone setups for performance, the main rules that I would follow were as follows:

  1. Use logistics drones to handle 'dumb' operations such as refilling/retrieval/etc.
  2. Use wait/breakpoints often in complex logic programs. I typically put 3min wait timers on taxing logic programs that are not critical. For a basic example if you had a farm set up, I may have a 15min or longer 'scan' gap due to the wait time needed prior to harvest.
  3. Personal preference, but I like to assign separate jobs/programs across multiple drones (at least early on when building out a routine). This allows for better debugging. For instance, if you have a chain of programs assigned across multiple drones, and you notice that performance tanks significantly once X drone in the chain activates, you can take a closer look at that section and investigate much easier. This does take more time initially, but can pay dividends if you intend on truly utilizing the flexibility that drones offer in automation.

Below I've included link to a video I made around 4 years ago showing some of the automation I set up in an absolutely massive Dome built with the drones. It includes the automation for producing all Pneumaticcraft parts along with full automation of all the Botania runes (at the time were virtually impossible to fully automate with any other mod). It's not 100% drone driven, but limited AE automation in conjunction. The video is kinda long, if you want to see the Botania stuff, skip to ~7:00. Also, this was ran locally and I didn't have the best PC at the time either and performance was no worse than any other heavily modded world.

https://www.youtube.com/watch?v=IYxwj4iVoTA

desht commented 4 years ago

@Tekstack excellent advice and I can't see any problems with it :)

Using multiple drones is indeed often a good idea. Also, while basic Logistics drones are great early on, don't forget that programmable drones can also use a Logistics puzzle piece, with much more flexibility over the area (smaller areas are good for performance, and don't forget you can have multiple single block areas), and you can insert extra pieces like a wait, or a standby (although 1.14.4 introduces a Standby Upgrade for basic drones which helps with that).

MuteTiefling commented 4 years ago

Just wanted to come back and say that the above advice has helped a lot. Specifically breaking things up.

I have made attempts to reduce the number of drones, however, and split things into bite sized chunks via network APIs. A good example of this would probably be my botania rune crafter. I have a chest filled with APIs each performing a small task, one to restock ingredients (basically just a logistics fetch if the buffer inventory is low), one for each rune, etc.

Each of those rune crafts starts off with a simple inventory check for one of the primary ingredients. If there's not enough, the rest of the program never runs.

Any loops internal to the programs also are given longish periods, relative to what they're doing. Like if I have to wait for a machine to process an item, I'll only poll the machine for the output item every second or so for fast machines and longer for slower machines. If the item isn't there, it waits again.

Finally, there's a long period standby program as the last api in the chest that puts the drone to sleep for several minutes.

By moving them into APIs I've made a system whereby I can very easily remove a faulty program that's causing performance issues without having to locate and trying to wrench the drone through bad lag. Just pop it out of the chest and the drone stops immediately.

With good naming conventions and frequent use of the Label/Jump pieces I can generally see exactly what they're doing and where they may be getting stuck, even if I can't watch the program run in the debugger.

And by passing in variables through the External program piece, I'm easily able to make generic programs that more than one drone can execute. Like my crop farm with four drones all handling their own small farms while sharing common code.

Overall, it's been a lot of fun learning this system. I feel I've gotten pretty comfortable making these programs at this point and rarely encounter any major issues with them anymore. It's a very solid system and very powerful. Thanks for all of your efforts with this mod!