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

Avoid duplication of mod metadata in memory #12562

Merged
merged 23 commits into from
Sep 26, 2022

Conversation

TurkeyMcMac
Copy link
Contributor

@TurkeyMcMac TurkeyMcMac commented Jul 19, 2022

I'd like mod storage to act more like a proper key-value database. It shouldn't store all the data in memory. With this PR, using the SQLite3 backend, the data is no longer kept in memory (unless SQLite3 chooses to do so.) The metadata interface has been split into IMetadata for the basic interface and SimpleMetadata for in-memory metadata. ModMetadata extends IMetadata. The interface only requires all data to be in memory when comparing two metadata maps and when converting metadata to a table. I could avoid this, but I'd rather not implement custom iterators and all that BS.

With this PR, mod writers can store huge amounts of data in mod storage without worrying about RAM limits, provided they are using the SQLite3 backend.

To do

This PR is Ready for Review.

  • C++ unit tests
  • Lua unit tests
  • minetest.features entry

How to test

There are unit tests in Lua and C++. You can also test with mods that use mod storage and other metadata.

@TurkeyMcMac TurkeyMcMac marked this pull request as ready for review July 20, 2022 01:38
@sfan5 sfan5 added @ Script API Roadmap The change matches an item on the current roadmap Feature ✨ PRs that add or enhance a feature labels Jul 20, 2022
@sfan5 sfan5 added the Rebase needed The PR needs to be rebased by its author label Aug 14, 2022
@Zughy
Copy link
Member

Zughy commented Aug 14, 2022

@TurkeyMcMac rebase needed

@Zughy Zughy removed the Rebase needed The PR needs to be rebased by its author label Aug 14, 2022
Copy link
Member

@sfan5 sfan5 left a comment

Choose a reason for hiding this comment

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

(code review only)

@@ -4868,6 +4868,9 @@ Utilities
get_sky_as_table = true,
-- VoxelManip:get_light_data accepts an optional buffer argument (5.7.0)
get_light_data_buffer = true,
-- When using an appropriate backend (not the deprecated "files" backend),
-- mod storage data is not necessarily all kept in RAM (5.7.0)
mod_storage_on_disk = true,
Copy link
Member

Choose a reason for hiding this comment

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

fuzzy as it is what is the practical application?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It means that, when using a non-deprecated backend, the size of mod storage is not limited by the available RAM. This doesn't include the dummy backend, which explicitly keeps everything in RAM. Perhaps I should change this comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The documentation has been changed.

Copy link
Member

Choose a reason for hiding this comment

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

No I understand what it means, but what are mods expected to do with this information?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If they detect this feature, they can basically store as much data as they want in mod storage.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

They wouldn't have to insecurely require lsqlite unless they needed a full-on relational database.

Copy link
Member

Choose a reason for hiding this comment

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

The problem I see here is that the feature entry only says "maybe it won't all be in RAM". If a mod relies on this and stores lots of data then -- depending on circumstances it cannot determine -- the engine might still run out of RAM.
For a mod the only safe way is to not store much data regardless of this feature flag. Therefore it's not useful.

Copy link
Contributor Author

@TurkeyMcMac TurkeyMcMac Sep 2, 2022

Choose a reason for hiding this comment

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

The updated documentation is more clear about this.

Copy link
Member

Choose a reason for hiding this comment

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

grafik
Maybe this diagram makes it clearer.
The problem I see is that mods cannot know for sure (*) that storing lots of data is safe.
(*) It is certainly possible to open world.mt and read the current backend. Aside from being obviously unportable we shouldn't encourage or support this way (API guarantees).

This is fundamentally the same reason why #12167 was rejected.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's unfortunate, but mods can specify in their READMEs that a backend should be used other than "files" or "dummy".

src/content/mods.cpp Show resolved Hide resolved
src/database/database-dummy.cpp Outdated Show resolved Hide resolved
src/database/database-dummy.cpp Show resolved Hide resolved
src/metadata.cpp Show resolved Hide resolved
src/metadata.h Outdated Show resolved Hide resolved
src/metadata.h Outdated Show resolved Hide resolved
src/script/lua_api/l_nodemeta.cpp Show resolved Hide resolved
src/script/lua_api/l_storage.cpp Outdated Show resolved Hide resolved
TurkeyMcMac and others added 11 commits September 26, 2022 07:27
This ensures that every instance of SimpleMetadata works with
nullptr passed as a place argument to getStringRaw.
It is no longer necessary to keep just one object per mod, since
data is no longer stored in these objects. Now one can obtain
multiple distinct references with core.get_mod_storage, but this
will be changed by PR minetest#12572.

One can test like so:

    local a = core.get_mod_storage()
    local b = core.get_mod_storage()
    a:set_string("!", "?")
    assert(b:get("!") == "?")
This bug was found by sfan5.
This is possible since registerModStorage was removed, at least.
@TurkeyMcMac
Copy link
Contributor Author

I rebased to remove registerModStorage and unregisterModStorage from DummyGameDef (and to fix conflicts.)

@TurkeyMcMac TurkeyMcMac merged commit f4a01f3 into minetest:master Sep 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature ✨ PRs that add or enhance a feature One approval ✅ ◻️ Roadmap The change matches an item on the current roadmap @ Script API
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants