Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove some unneeded memory allocation #614

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

TurkeyMcMac
Copy link
Contributor

@TurkeyMcMac TurkeyMcMac commented May 20, 2022

Overview

This PR does three things:

  • Clean up the basic info getters like mesecon.get_conductor.
  • Speed up the functions for finding node links, remove unnecessary allocations.
    • As far as I can tell there can only be one linking rule between two nodes, so the functions have been simplified.
    • The inverted function now returns the actual rule, not the inverted rule.
  • Remove unnecessary node copies.
    • Components in the modpack with rule getter functions are passed non-copied nodes. External components can get non-copied nodes as well by putting the rule_node_nocopy key in their definitions.

Benchmarks

I used the benchmarks from #578. Keep in mind that reducing garbage collection load may also increase the performance of code outside mesecons.

Long line of diodes

Before: 0.11s
After: 0.10s (probably within margin of error)

Block of wires

I turned the block on and off 10 times.

Before: 1.7s
After: 0.8s

256 byte memory bank

Before: 1.5s
After: 1.3s

Tests

I've done manual testing and things work. The tests from #605 also pass.

The function was supposed to return an outputrule, but before it
inverted the returned rules, so these usages of the function
expected inverted rules.
local function get_rules(def, node)
local rules = def.rules
if type(rules) == 'function' then
if not def.const_node then
Copy link
Member

Choose a reason for hiding this comment

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

Do you happen to know where this would be documented?

Also: How much of a performance difference are we talking about here? A new variable and checks to skip a table creation with three indices seems to be overkill - at least to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure where this should be documented. I can't tell the source of the documentation at https://mesecons.net/developers.html.

I think avoiding copying is worth it, since the garbage collector is a known limitation to the speed of LuaJIT. If you have 10k insulated wire segments, that's 10k allocations saved.

Copy link
Member

@SmallJoker SmallJoker May 29, 2022

Choose a reason for hiding this comment

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

I believe that code complexity (O) matters most. If the function calls are proportional to the amount of placed wires, such an optimization does not seem to be urgent due to "sane" linear scaling in computational. Of course it does make a small difference, but nothing compared to the case if it would scale by O(n²). Hence the time used by an allocation and later GC appears negligible.

Either way ... what would you think of renaming the variable to rule_node_nocopy? action_on still receives a copy after all.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Optimizations to the code complexity have the highest yield, but eventually the only optimizations left to do involve reducing the constant factor. I think these are still important since people use Mesecons to build vast contraptions such as whole computers. In these cases, even a 1% optimization reduces the absolute execution time by a lot.

I will rename the variable to rule_node_nocopy.

@TurkeyMcMac
Copy link
Contributor Author

Perhaps someone with the right privilege can run a search of ContentDB for mods using rules_link_rule_all and rules_link_rule_all_inverted. I know lwwires uses them. If they are used by many external mods, I will provide new implementations of them for compatibility with these mods.

@rubenwardy
Copy link
Contributor

https://content.minetest.net/zipgrep/43bc7f2d-403d-4bc4-84bf-3ba524da579d/

@TurkeyMcMac
Copy link
Contributor Author

Thanks. It looks like lwwires is the only one.

@TurkeyMcMac
Copy link
Contributor Author

I decided to reimplement the functions regardless.

@TurkeyMcMac
Copy link
Contributor Author

By the way, this code could be simplified and sped up a bit if it were assumed that the functions which return rules do not modify the node tables passed to them. This assumption is not the norm in the Minetest API, but it seems realistically true.

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.

4 participants