Page 2 of 2

Re: Energy Optimization with Red Inserters

Posted: Thu Dec 19, 2024 1:52 am
by evanrinehart
To be clear I was just looking at sustained moving of items from box to box, no idling at any time. To be sure, in this situation the drain is certainly costing you to move the items. And the amount differs depending on the inserter type. So ignoring it would give wrong answers in this case.

Many other comparisons in other situations can be made, with other activity profiles.

Re: Energy Optimization with Red Inserters

Posted: Thu Dec 19, 2024 2:21 am
by Muche
I realize you are trying to experimentally deduce/confirm the energy usage, but I thought it might be useful to look at inserters definitions to see what variables they use, possibly even experiment with them (like making them 100 times greater to clearly see their effect):
inserters

Re: Energy Optimization with Red Inserters

Posted: Thu Dec 19, 2024 4:15 am
by GregFirehawk
So I've gone ahead and adapted my test from before to measure burner inserters. Here is the adjusted blueprint

Code: Select all

0eNrNWEtu2zAQvQvXUmDqZ8lAu+4mq2RnBII+tE1EolSSSuoGOkBu0U0v1pN0qL9rOY6UGnEWwWjImeF7M8Nh8oLCpCA5p0yi1QuiUcYEWq1fkKBbFiRKx4KUoBWKSURjwvUoS0PKAplxVGqIspj8QCtcPmiIMEklJbV99bH3WZGGhMMGrfVDEhJJTiOdMMK3ex0iE74JIoI0lGcCPGRMhVVeDUdDe7TSTbyEWGGx2RDuC/oT/OBF91NqR+GMLlyePcOhxTOV0W4sgjuMAOglzxI/JLvgiQJC2BVRHhVU+oQFYUJitJK8IFqnBpO487ihXEi/p07uc3WGJ8plAZruUPUOfcsJYaiOK2SgUrBQH2ke8IrgFfqCSlivj+/DHgnmmyARZAS0qb2Rq2Po5uLGHoKPKYfMVBvccSoatz1mURE0+Fofc9AcifKM6XmiAJT/YPyKVPVkhcwLeaL4htblQ1mOoLcmosdXgv7P6+838L+vgk5QYk+jxLB7SuyLUxJl8HlQ+/i49ufyEiZB9Fh7z/dwvIJJf8Oz1KcMnLUtNM6aM5E153NYm9ZAtd0JxMsOMWUbymBJj3ZEyDG0yx6tdWNXE6A28QWRkrJtBYaTNHsifgFrCVzvJPapJKloL89aWx/1uEMUuqIqiAVch2kWq/VA6gkJqjN1M0c7hNfZ2W+ZGYqEYw7cjoOUxLRI9W5O5VkyOpvcQd6BiRGfXuczLDhMO5h1gnBAfsZdTeygkLBxjbPpz+uvakMTjZMg9ncBi1VcCVQ06YYtUAucQ82rCRY9thN8hDG8mFCK3sdLcSxruH+rtNjfP0qOUmeNZ07U6+JQhnZoi/uwSXrtmbTdg+Y7LAAgULKMp01jHNyrfYdBM4zfCdiYPzzMy12DZ+DfHlass/h/I+XbyesTT3x4De/Qz6Pq7nJU3c6cvNiaP3qvqOY+wtspZqY+5dyrLLHZzNydZmbqc827BmbuL9d8d3Obbzn/D6jPI3Lw0H/ng/h8Zk4R5M7/+/qKKu3DzID9M0BR1mtDw5qlmQ/a2gTJbCQTdLiRvEqyDiQoNSXaYOJUJnavdDqlkmobeJHhdh2rkPDL7OQ6PlYHgGuykU2lr/Zbgz32YE8l15GwCgXpreSlsnVrW7fVA2b1alQv+e7fZRqCV62o8mk7hmd5nm15hutYi7L8C5epid4=
coal pulse.png
coal pulse.png (923.84 KiB) Viewed 885 times
Everything is the same as before except those two new inserters on the left. Earlier in the top right we had our item counter and our GO condition. Here I have kept those in place, but added a separate counter and signal emitter for coal. The test is formulated like this. First the hungry burner will grab two pieces of coal to feed itself upon receiving the GO signal. The clock is no longer tied to our go signal, and is instead tied to our new signal. When the coal counter reaches 3 coal, it will start the clock, and when it reaches 4 the clock will turn off.

The reason we do this is because after observation there are two things clear about burners. The first is that they have some non visible buffer of energy that is not part of the bar, making measuring to exhaustion a potentially inaccurate measure of power consumption, as we are introducing an undocumented element. The second is that after the visible fuel bar is empty, it will immediately try to refuel itself. We can assume this is conditioned such that the moment it enters or is about to enter its invisible fuel reserve, it will refuel itself. What this means plainly is that it will always consume the full visible bar before refueling itself, which makes for a consistent test condition. The fuel bar also dynamically sizes itself to always be full at exactly 1 unit worth of fuel, regardless of the actual energy of the fuel being used.

Having run the test our clock reads 1 minute, 14 seconds, and 24 ticks. Just like with our original pulse test, we need to subtract 1 tick for the inserter picking up the piece of coal that triggers the stop condition, and then 2 ticks for the delay before the clock responds to the change. Meaning we actually have 1 minutes, 14 seconds, and 21 ticks or 74 seconds and 21 ticks or 4461 ticks

This is the exact duration of time the inserter took to consume 1 piece of coal, or 4MJ of fuel, which makes our next calculation easy.

(4MJ / 4461) * 60 = 53.799596503026 kW

So according to our test, the inserters effective kW rating is actually ~53.8kW. This is slightly different to the earlier finding presented in this thread of 52.511kW Given this testing methodology is a bit more scientific, I'm more inclined to trust my test. Still I will rerun the rest with a couple other fuels to see if the skews the results.

Before I report my results I wanted to share an interesting thing I noticed. When devising this test I did not bother to put a filter on the inserters because the test just worked. To my surprise though when I went to test solid fuel, the inserters actually began moving that instead of the testing plates. Just a weird quirk how that works.

Testing with wood gave us a measurement 36 seconds and 21 ticks or 2181 ticks This is different from the value we would expect given that this is exactly half the energy.

(2MJ / 2181) * 60 = ~55.0206kW

According to this test we lost an entire 1.2kw just by switching fuel!

Solid fuel tests at 3 minutes, 45 seconds, and 5 ticks or 225 seconds and 5 ticks or 13505 ticks

(12MJ / 13505) * 60 = ~53.31358756

Here we have regained the missing 1.2kw, and gained an additional 0.5kw over coal. If I had to guess, this discrepancy comes from where in its rotation cycle the inserter runs out of fuel. It is possible that this is because energy in the invisible buffer is not free, so it reclaims that energy from our fuel, meaning our measurement is effectively shortened as energy from the cycle we are trying to measure is being eaten by the deficit from the previous cycle. To confirm this, I will run the test with several more clock setups, each measuring a different fuel cycle. If our finding is true, we should be able to confirm variability in the times even when using the same fuel. Because the measurements start and end with the grabbing of an item, we know we are always at the same angular position at the start and end of each cycle, so this is not a factor.

I expanded the coal test to included 3 additional clocks, and found that the first two clocks, as well as the last clock, all three matched perfectly. The third clock though was a full 65 ticks behind the other 3, and there no discernible reason. I then expanded the test to include 12 clocks total. Looking at our new clocks, we see a pattern emerge. All of our clocks give identical results, except for clocks 3, 8, and 12, which give the same faster result from before. The behavior is clear, but its not very consistent, and I'm struggling to define the pattern. My best guess is the game is trying to compensate for a rounding error somewhere by spreading it out like leap years, but due to the inconsistent pattern its difficult to discern exactly what the remainder is. We'd need to plot this in more detail to figure anything out further, but that requires more clocks. Even just copy and pasting these clocks is sort of a pain as you need to adjust the value each time, and make sure not to forget to plug any of them in, so thats all I will share for today.

If someone wants to run the clocks and build a plot, we can determine the exact power consumption of the burners in kW. With that information we can time a single spin, subtract 2 ticks from it of 144kw, and get all the same numbers as the other inserters like before.

Speaking of that I quickly measured spin times so we wouldn't need to later. Using the refueling as an indicator to start the timer, we measured 129 ticks. Without refueling a pure spin is 76 ticks. Thus we can assume that each fuel insertion takes 53 ticks, and I have confirmed this through measuring. Interestingly when we time a virgin inserter, it starts its life by inserting 2 pieces of fuel back to back, and that process takes 112 ticks, which is more than what we calculated before. It is not clear where the extra 6 ticks go. This doesn't really have practical relevance though as it is a virgin action, and we have confirmed that in practice 53 ticks per fuel load is the value. Also we can confirm that our speed of 76 ticks is marginally better than the games official numbers of ~76.86. One thing worth exploring is whether the game actually logs this remainder and adds an extra tick back in every ~7.6 spins. This would be worth checking with other inserters inserters also.

Anyway thats all for now. Hopefully someone can do some more testing so I don't have to. I really don't want to set up all those clocks :(

Re: Energy Optimization with Red Inserters

Posted: Thu Dec 19, 2024 4:29 am
by GregFirehawk
Muche wrote: Thu Dec 19, 2024 2:21 am I realize you are trying to experimentally deduce/confirm the energy usage, but I thought it might be useful to look at inserters definitions to see what variables they use, possibly even experiment with them (like making them 100 times greater to clearly see their effect):
inserters
Wait, that data is just lying around in plain text somewhere? Wow that is annoying. If the developers already reveal it so openly, why the hell is this info not on the god damn wiki :evil:

Here I am crunching numbers like I'm trying to cure cancer, and the answer was just somewhere all along :evil:

Well thank you for sharing that at least. Can I ask where you got the data? Is it just in the game folder somewhere as raw code?

To some extent this does make my life much easier, as I can derive all the same information without needing experimental data now. I can just use my earlier equations with these hard coded values, and then compensate for tick rounding. At least I think thats how that works. I noticed a 400W discrepancy between the hard coded value and the empirical value which I am assuming is from the tick rounding on the rotation.

Damn that really rocked my world. Seriously, where did you get the data from?

Edit: I just noticed this data doesn't actually explain the pulse behavior for the max consumption. Or at least its not obvious to me how it would. Is there perhaps some more code somewhere to account for that?

Re: Energy Optimization with Red Inserters

Posted: Thu Dec 19, 2024 6:44 am
by evanrinehart
The pulsing might be related to the "fixed energy per cycle" thing I mentioned way back at the beginning of the thread. The config file shows fixed energy per rotation and energy per "movement." And they're the same amount. So if these different phases last very different amounts of time, the derived power draw will look very different. It doesn't look like enough information to predict average power though.

Re: Energy Optimization with Red Inserters

Posted: Thu Dec 19, 2024 9:17 am
by Muche
GregFirehawk wrote: Thu Dec 19, 2024 4:29 am Can I ask where you got the data? Is it just in the game folder somewhere as raw code?
Yeah, they are in data/base/prototypes/entity/entities.lua and data/space-age/prototypes/entity/entities.lua.

As I understand it, this data is used to configure the behaviour of compiled code, so things like the grabbing energy spikes do need to be verified experimentally. Having access to this data just allows for focused tests, like, all drain is zero, rotation is extra slow, etc. to suss out the precise cycle.

Re: Energy Optimization with Red Inserters

Posted: Thu Dec 19, 2024 2:00 pm
by GregFirehawk
evanrinehart wrote: Thu Dec 19, 2024 6:44 am The pulsing might be related to the "fixed energy per cycle" thing I mentioned way back at the beginning of the thread. The config file shows fixed energy per rotation and energy per "movement." And they're the same amount. So if these different phases last very different amounts of time, the derived power draw will look very different. It doesn't look like enough information to predict average power though.
Looking at our experimental data from the red Inserter that doesn't seem to be what's happening. The values are identical to each other so even if the phases overlap they'll only produce a max value that is twice as much, but we can see the power spikes are more than that. The only time we see that actually seems to be during the virgin inserter scrunching, where if we look at the original chart we can see it does briefly move at double the typical value. There must be another rule somewhere regarding an energy cost to picking up an item that isn't listed in these parameters.

Re: Energy Optimization with Red Inserters

Posted: Thu Dec 19, 2024 4:49 pm
by evanrinehart
First section of FFF-309 where they lament the lack of understandable inserter performance and propose to simplify it. I for one glad they didn't!

https://www.factorio.com/blog/post/fff-309

Re: Energy Optimization with Red Inserters

Posted: Fri Dec 20, 2024 1:45 pm
by GregFirehawk
Having sat with the numbers for a bit, I still for the life of me cannot figure out why there is a ~400W discrepancy between my value and the games hardcoded value. That's not an insignificant difference either, thats like 8% more. Yet despite calculating an 8% higher value than what was hardcoded by the game, my final number for operation cost is still slightly lower than Evan's finding. I'm quite stumped on how that works out. If anyone wants to look into this further, I would appreciate an update.

I have ultimately gotten enough data for my original practical needs, which was the optimal choosing of inserters, so I won't be looking into this further. Since the methodology, blueprints, and equations were all shared, anyone interested can continue where I left off if they wish. I'll be updating the original top post with the final finding as a general rule of thumb, so anyone stumbling across this can have access to accurate information without having to look all the way through.

Edit: As I was getting ready to wrap this up, I noticed the games hard coded values are actually off by much more than is usable or explainable, so I ultimately abandoned that course of action, and this remains an open issue.

Re: Energy Optimization with Red Inserters

Posted: Fri Dec 20, 2024 9:50 pm
by GregFirehawk
I realized that for my final finding to make sense I would need to share some more relevant data. Firstly I have confirmed Evans finding that blue and green inserters have a spin time of 24 ticks. This doesn't really make sense as red inserters are 50 ticks, and these inserters are exactly twice as fast, meaning we should be getting 25 ticks, yet the number is 24 despite that. Once again this is a discrepancy that has no real explanation.

Anyway doing all the same calculations as before we find a cost per motion of ~47.957kw, a cost per spin of ~23.1844kJ, and an operating cost of ~58.961kw. This is once again quite similar to Evans empirical data, but very different to the games hard coded data. It also makes me question if I misinterpreted the data when looking at the yellow inserter since the games hardcoded value is 5kj, I assumed this meant it would use 5kw when moving, but now looking at the green inserter as reference that actually seems to be kJ per full spin, not kw cost of motion as I originally interpreted. In that case me and the game actually have a discrepancy of ~1.6kJ on the yellow inserter, and our discrepancy on the green inserter is twice as high. This unfortunately means we can't actually trust the game, as it seems to just be lying about everything at every turn. Even something as basic as the inserters spin speed. Sure the yellow and burner inserter had a rounding error so we can understand, but the green and blue inserters should be doing exactly 25 ticks per spin. Its perfect math, and yet they do 24.

At this point my attempts to walk away have been foiled as I am completely baffled by this. I was ready to just use the in game data to make some calculations assuming they'd be accurate as long as tick rounding wasn't introduced, but for no reason at all that doesn't work. Those devs are cheeky liars, and now I've been sucked right back in. Interestingly our numbers for the red inserter seem to be basically perfect with what the game tells us, its just all these short ones that make no sense.

Anyway since I'm already here I'll just do the blue inserters. Originally I was going to neglect them since they should obviously just be worse in every use case, but given the game has lied about everything else so far we need to confirm this as well. Once again I confirmed 24 ticks rotation (so thankfully that is consistent at least). We get a cost of motion of ~16.7414 kw, a cost per spin of ~8.1151kJ. Interestingly, though this is still objectively the worst inserter in terms of kJ per item, the disparity is not as huge as the game leads you to believe. ~6.6kJ for the yellow inserter, almost a perfect 7kJ for the red, and for the blue just ~8.1kJ. Anyway this gives us an operating cost of ~20.7879kW.

For the burner inserter, I still haven't collected better data than before, so this number won't be as accurate as it could be, but just so we have something for reference for current comparison I'll finish the calculation with the data from last time. I'll be using the operating cost from coal as the reference, as I am most interested in their practicality fueling boilers with coal in the early game. Obviously solid fuel is three times denser, so if they can do coal they can do solid fuel easily. If you are interested in the solid fuel use case you are welcome to do the calculation as all the data is present. the ~53.8kw operating cost from coal can be reverse engineered into our previous equations, giving us a cost per spin of ~68.1466kJ. For completeness I will also derive the cost of motion, though we don't actually need it for anything at this point, and that value is ~51.36216kW.

Now lets derive the actual interpretation of this data. Which inserter should be used at how many item/s. I went ahead and whipped up some graphs in python because I'm cool like that :ugeek:
download.png
download.png (612.59 KiB) Viewed 732 times
Source code for the graph

Code: Select all

import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.axes_grid1.inset_locator import zoomed_inset_axes

stack_size = 1
green_stack = 2

yellow_speed = 60 / 70
red_speed = 60 / 50
blue_speed = 60 / 24

burner_energy = 68.1466 
yellow_energy = 6.65203
red_energy = 7
blue_energy = 8.1151
green_energy = 23.1844

yellow_drain = 0.4
blue_drain = 0.5
green_drain = 1

x = np.linspace(0, 2.5 * green_stack, 300)

yellow_mod = x % (yellow_speed * stack_size)
red_mod = x % (red_speed * stack_size)
blue_mod = x % (blue_speed * stack_size)

burner = (burner_energy / stack_size) * x
yellow = ((yellow_energy / stack_size) * x) + (yellow_drain * (((x / yellow_speed) - yellow_mod) + 1))
red = ((red_energy / stack_size) * x) + (yellow_drain * (((x / red_speed) - red_mod) + 1))
blue = ((blue_energy / stack_size) * x) + (blue_drain * (((x / blue_speed) - blue_mod) + 1))
green = ((green_energy / green_stack) * x) + green_drain

fig = plt.figure(figsize = (12, 15), dpi = 300)
ax = plt.axes()

ax.plot(x, burner, label = "Burner", color = "black")
ax.plot(x, yellow, label = "Yellow", color = "orange")
ax.plot(x, red, label = "Red", color = "red")
ax.plot(x, blue, label = "Blue", color = "blue")
ax.plot(x, green, label = "Green", color = "green")

ylim = 60

ax.set_ylim(0, ylim)
ax.set_xlim(0, blue_speed * green_stack)

xtick = 0.2 * green_stack
ytick = 2

ax.set_xticks(np.arange(0, blue_speed * green_stack + xtick, xtick))
ax.set_yticks(np.arange(0, ylim + ytick, ytick))

ax.set_title("Inserter Efficiency (No Capacity Bonus)")
ax.set_xlabel("Items / second", fontweight = "bold")
ax.set_ylabel("Power Cost (kW)", fontweight = "bold")

ax.grid()
ax.legend(loc = 4)

zax = zoomed_inset_axes(ax, 2.2, loc = 2, borderpad = 1)
zax.yaxis.tick_right()

zax.plot(x, burner, label = "Burner", color = "black")
zax.plot(x, yellow, label = "Yellow", color = "orange")
zax.plot(x, red, label = "Red", color = "red")
zax.plot(x, blue, label = "Blue", color = "blue")
zax.plot(x, green, label = "Green", color = "green")


zylim = 10
zxlim = red_speed * stack_size

zax.set_ylim(0, zylim)
zax.set_xlim(0, zxlim)

zxtick = 0.1 * green_stack
zytick = 0.5 

zax.set_xticks(np.arange(0, zxlim + zxtick, zxtick))
zax.set_yticks(np.arange(0, zylim + zytick, zytick))

zax.grid()

plt.show()
So here are our default values. As you can see burners shoot off into the sun so we practically can't make out what they're doing at all. I added a zoom in to help clarify some things in the initial corner. The graph is setup so that when an inserter reaches its maximum capacity, it will be assumed a second inserter is being used in tandem to continue increasing throughput. This is why the graph has those bumps, as a second inserter worth of drain is added.

Now we can continue generating quite a few variations of these graphs at various stack sizes. I've decided its a bit impractical to just bombard people with literally dozens of graphs, so we'll just focus on some key ones. First we will show at what point burners become more profitable than yellow inserters. To do this we will just inverse the x axis on our graph by flipping our speed values, and a little finagling with the code so it looks right, and we get this:
download2 (2).png
download2 (2).png (472.5 KiB) Viewed 732 times

Code: Select all

import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.axes_grid1.inset_locator import zoomed_inset_axes

stack_size = 1
green_stack = 2


yellow_speed = 70 / 60
red_speed = 50 / 60
blue_speed = 24 / 60

burner_energy = 68.1466 
yellow_energy = 6.65203
red_energy = 7
blue_energy = 8.1151
green_energy = 23.1844

yellow_drain = 0.4
blue_drain = 0.5
green_drain = 1

x = np.linspace(0, 300, 300)

yellow_mod = x % (yellow_speed * stack_size)
red_mod = x % (red_speed * stack_size)
blue_mod = x % (blue_speed * stack_size)

burner = (burner_energy / stack_size)
yellow = (yellow_energy / stack_size) + (yellow_drain * x)
red = (red_energy / stack_size) + (yellow_drain * x)
blue = (blue_energy / stack_size) + (blue_drain * x)
green = (green_energy / green_stack) + (green_drain * x)

fig = plt.figure(figsize = (15, 10), dpi = 300)
ax = plt.axes()

plt.axhline(y = burner, label = "Burner", color = "black")
ax.plot(x, yellow, label = "Yellow", color = "orange")
ax.plot(x, red, label = "Red", color = "red")
ax.plot(x, blue, label = "Blue", color = "blue")
ax.plot(x, green, label = "Green", color = "green")

ylim = 70
xlim = 160

ax.set_ylim(0, ylim)
ax.set_xlim(0, xlim)

xtick = 5
ytick = 2

ax.set_xticks(np.arange(0, xlim + xtick, xtick))
ax.set_yticks(np.arange(0, ylim + ytick, ytick))

ax.set_title("Inserter Efficiency (No Capacity Bonus)")
ax.set_xlabel("Seconds / Item", fontweight = "bold")
ax.set_ylabel("Energy / Item (kJ)", fontweight = "bold")

ax.grid()
ax.legend(loc = 4)

plt.show()
This data is pretty self explanatory, and I've zoomed in on points of interests. As we can see there is a point where a red inserter does become more efficient than a yellow one, and that is when a single yellow inserter is maxed so you'd need a second one, but the single red inserter still has some breathing room. As for the burner, we find that it becomes the best inserter when moving less than 1 item every ~2.5 minutes. Remember all inserters are subject to the same ratio since they share a stack size, except for green inserters. But the green inserter never makes a dent in that graph regardless of its stack size advantage, so there's no point in looking further. Just divide the time by the stack size to account the upgraded time. Also remember our numbers for the burner might not be perfectly accurate.
download3.png
download3.png (601.46 KiB) Viewed 732 times

Code: Select all

import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.axes_grid1.inset_locator import zoomed_inset_axes

stack_size = 2
green_stack = 6

yellow_speed = 60 / 70
red_speed = 60 / 50
blue_speed = 60 / 24

burner_energy = 68.1466 
yellow_energy = 6.65203
red_energy = 7
blue_energy = 8.1151
green_energy = 23.1844

yellow_drain = 0.4
blue_drain = 0.5
green_drain = 1

x = np.linspace(0, blue_speed * green_stack, 300)

yellow_mod = x % (yellow_speed * stack_size)
red_mod = x % (red_speed * stack_size)
blue_mod = x % (blue_speed * stack_size)

burner = (burner_energy / stack_size) * x
yellow = ((yellow_energy / stack_size) * x) + (yellow_drain * (((x / yellow_speed) - yellow_mod) + 1))
red = ((red_energy / stack_size) * x) + (yellow_drain * (((x / red_speed) - red_mod) + 1))
blue = ((blue_energy / stack_size) * x) + (blue_drain * (((x / blue_speed) - blue_mod) + 1))
green = ((green_energy / green_stack) * x) + green_drain

fig = plt.figure(figsize = (12, 15), dpi = 300)
ax = plt.axes()

ax.plot(x, burner, label = "Burner", color = "black")
ax.plot(x, yellow, label = "Yellow", color = "orange")
ax.plot(x, red, label = "Red", color = "red")
ax.plot(x, blue, label = "Blue", color = "blue")
ax.plot(x, green, label = "Green", color = "green")

ylim = 60
xlim = blue_speed * green_stack

ax.set_ylim(0, ylim)
ax.set_xlim(0, xlim)

xtick = 0.6
ytick = 2

ax.set_xticks(np.arange(0, xlim + xtick, xtick))
ax.set_yticks(np.arange(0, ylim + ytick, ytick))

ax.set_title("Inserter Efficiency (Capacity Bonus 4)")
ax.set_xlabel("Items / second", fontweight = "bold")
ax.set_ylabel("Power Cost (kW)", fontweight = "bold")

ax.grid()
ax.legend(loc = 4)

zax = zoomed_inset_axes(ax, 3, loc = 2, borderpad = 1)
zax.yaxis.tick_right()

zax.plot(x, burner, label = "Burner", color = "black")
zax.plot(x, yellow, label = "Yellow", color = "orange")
zax.plot(x, red, label = "Red", color = "red")
zax.plot(x, blue, label = "Blue", color = "blue")
zax.plot(x, green, label = "Green", color = "green")


zylim = 10
zxlim = red_speed * stack_size

zax.set_ylim(16, 24)
zax.set_xlim(4.2, 5.4)

zxtick = 0.2
zytick = 0.5 

zax.set_xticks(np.arange(4.2, 5.4 + zxtick, zxtick))
zax.set_yticks(np.arange(16, 24 + zytick, zytick))

zax.grid()

plt.show()
Now this is is a very interesting graph. Remember that between Capacity Bonus 2 and Capacity Bonus 7, the only inserter affected is the green one, and all the others remain the same at a a stack size of 2. The graph actually tells us a couple different things. Firstly, at capacity bonus 2 we can see that the red and yellow inserter now regularly exchange in a kind of interlaced pattern. That means for anyone trying to optimize efficiency it actually is important to reference the graph and maybe do the calculation. Very cool! We can also that the blue inserter is always more expensive if not equally expensive to the other inserters, except for a brief point around 4.9 items per second where it does actually become cheaper than red inserters. I think this range is too small to have any practical significance, but its noteworthy. We can also see that at a throughput of 5 items per second or higher, green inserters begin destroying blue inserters. This is the first time a green inserter overtakes one of the other inserters in the game, which is why I chose capacity bonus 4 for this graph.
download4.png
download4.png (581.47 KiB) Viewed 732 times
Here we can see Green Inserters start dominating. The other inserters only remain viable in the lower throughputs. Granted there are still many use cases with a throughput that low, but it really doesn't take very much at all for the green inserter to pull ahead stupendously. We can also see that by this point the blue inserter has become completely obsolete. At capacity 4 it will still barely holding onto relevance, but now its just completely smoked. Here is the green inserter being even more dominant:
download5.png
download5.png (445.46 KiB) Viewed 732 times
Finally the coup de grace, Capacity Bonus 7:
download6.png
download6.png (573.84 KiB) Viewed 732 times
Here we can see the blue inserter regain a little bit of relevance over its counterparts, but the green inserters still blow all of them away. We can see from the zoom in this occurs around a throughput of 1.5 items/s, and before that the red and yellow inserters dominate. Also interestingly on our zoom in we see that red inserters have somehow overtaken yellow inserters? I'm not really sure how that's possible as their relationship should be proportional between stack sizes, and the red ones actually have a slightly higher slope while they share an identical drain. This is a real mystery to me. Still this difference is miniscule enough I am willing to pretend I didn't see it for my own sanity. If anyone can figure this out I'd be very interested to hear the explanation.

Hopefully everyone finds this information, though more work still needs to be done on this topic. For one our burner was never properly studied in detail, and all of this data is exclusively chest to chest, so we haven't accounted for any inefficiency a belt may introduce. I imagine that is very relevant to the green inserters especially.

Re: Energy Optimization with Red Inserters

Posted: Fri Dec 20, 2024 9:54 pm
by GregFirehawk
I've realized a glaring problem the moment I finished hitting submit on all those graphs. All of the calculation are based on a cost per spin formula that accounts for 2 ticks of item spike. However if we increase the stack size on a belt, we should have an item spike for each item, meaning there are actually stack_size + 1 item spikes per spin. Meaning these calculations are practically useless for the primary use case in the game! And thats not even mentioning the extra movement cost of scooping up all these items individually :cry:

I don't know if I'll get around to doing belt tests and gathering the relevant data, as at this point its becoming a lot of work. If you're reading this, please help lol

Re: Energy Optimization with Red Inserters

Posted: Tue Jan 07, 2025 8:32 pm
by GregFirehawk
I started doing belt tests and realized its a bit of a moot point. Firstly even if you could do it, the power graph is too messy to really quantify accurately with the games limited power tools. But then I realized that since every item gets a tick of item spike, that completely nullifies any savings you might have from movement. So when loading from a belt, you may as well be at stack size 1 on the chest to chest sheet, just adding an extra tick of max consumption for each extra item. That already nullifies any need to calculate wiggling or anything else as the difference becomes too large to be compensated for. In practice that means when feeding belts, you should just reference the no stack bonus chest to chest graph to determine which option is most efficient, as the differences between options would just be further amplified in a linear fashion. It also means that brief moment where red inserters gain supremacy disappears with a stack bonus. So ironically after all that work it turns out we arrive back the simplest assumption every new player makes, which is the yellow is the true cheapest, and each tier up becomes progressively more expensive to operate. This functionally disproves what a lot of players say about green inserters being cheapest in the end game, because as we can see that doesn't apply to belts.

Also in regards to quality, it seems to be a linear 30% in speed, so these differences will remain consistent across quality tiers. The higher tiers cost more power, but only because they are moving more items, so they're equally efficient across quality tiers. Technically there is a saving on drain, but it doesn't affect the relationships in anyway. If you want to compare across quality tiers for some reason, you can continue to reference the earlier data, just remember to multiply the values by the appropriate quality tier. 30% increase per tier.

So it turns out I had effectively fully solved the problem already last time without realizing :D

Re: Energy Optimization with Red Inserters

Posted: Tue Jan 07, 2025 10:28 pm
by Khazul
If you have issue with the power consumption of belts, what are you going to do? Get a bunch of people to join your game to serve as energy free labour to cart stuff around? ;)

Perhaps a mod to use biters as free labour?

Re: Energy Optimization with Red Inserters

Posted: Thu Jan 09, 2025 10:46 am
by GregFirehawk
Today a video popped up on my feed that was recently uploaded on this topic. That person attempted belt tests more vigorously than me, and while he ultimately didn't find much new information, I did catch an oversight on my end. Apparently when unloading onto a belt, the power behavior is identical as when unloading to a chest. So unlike when loading, there are no individual power spikes. Instead the inserter simply turns off and waits for the entire stack to drop, before producing a single power spike when its finished its delivery. That means the total power use is identical as chest to chest in chest to belt. Only belt to chest creates erratic behavior.

So when unloading your machines or chests, you can still get all those nice benefits with green inserters, just not when loading them from a belt

Re: Energy Optimization with Red Inserters

Posted: Thu Jan 09, 2025 12:46 pm
by GregFirehawk
While preparing to collate these findings and add them to the wiki, I noticed something very exciting. After digesting my last comment about inserter unloading, I took another look at the belt loading power curve, and found that while it is confusingly and inexplicably erratic, after looking at various configurations of different inserters its obvious that there is also only one true power spike regardless of stack size. The erratic nature we are seeing is just confusing movement
yellow belt pulse.png
yellow belt pulse.png (30.44 KiB) Viewed 465 times
Here I am doing belt to belt transfers. Using this example we can see a very clearly defined power spike right at the end of the complicated pick up pattern.There are a bunch of other smaller spikes and dips which don't have an explanation. My theory is this averages out to the cost of rotation plus the cost of extension/retraction, which we know to be just the cost of motion doubled from the games code. This graph also says its ~11kw, which would be correct for a yellow inserter given our derived data. Of course we can't actually trust the game at all, because it also says the cost of rotational movement is 4.6kw in this same graph, which I have already personally confirmed is BS.

This same behavior is consistent across all inserters combinations and configurations. There is a very clearly defined distinctive spike. This also means these spikes aren't actually from items, but rather from the inserter initializing a new command.

So if we imagine the inserter to have code, it takes a load instruction, does its best to do that, then it does an unload instruction. Only when transitioning between these instructions does it actually spike; the rest of the time it just consumes normal movement costs. That means if my theory is right then it would still benefit from stack bonuses even when belt loading, just much less.

We could put it into our graphs like earlier, which would be best, but I can't confirm the actual value is what I'm guessing it is. Also thats only hypothetically true as an average, but there are scenarios where it seemingly is not true. For example when loading the yellow inserter off an express belt with a low stack size, what we see in the power panel doesn't really suggest this is true. Of course we can't actually trust the power panel so its a toss up. Not really sure what to do about this.

To recap the open question of the thread:
  • Burner Inserters still have an ambiguous power consumption, and much more extensive testing is needed to narrow down the true value :not-enough-repair-packs:
  • Belt loading has erratic and variable power consumption, which also requires more such testing :not-enough-repair-packs:
It would be really great if the community could help provide data here. People were being very helpful earlier but that seems to have fizzled out