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

Use a LevelDB to store playerdata NBT instead of flat files #4077

Closed
dktapps opened this issue Mar 14, 2021 · 11 comments
Closed

Use a LevelDB to store playerdata NBT instead of flat files #4077

dktapps opened this issue Mar 14, 2021 · 11 comments
Labels
Category: Core Related to internal functionality Performance Resolution: Won't fix Will not be worked on Type: Enhancement Contributes features or other improvements to PocketMine-MP

Comments

@dktapps
Copy link
Member

dktapps commented Mar 14, 2021

Description

The server should store players' data in a LevelDB database instead of dumping them into lots of .dat files on the disk.

Justification

The current system of playerdata storage uses flat .dat NBT files on the disk. This is horribly inefficient for several reasons:

  • Player .dat files are typically very small (a couple of kb). Considering that typical filesystems use a 4KB allocation unit size, this means that a significant percentage of disk space gets wasted (e.g. a 6KB data file occupies 2 sectors, totalling 8KB)
  • No readahead is possible with many flat files, so the data can't be cached in memory, leading to longer I/O wait times.
  • Compression has reduced efficiency. Considering that player.dat files contain a lot of common data (mostly NBT keys), compressing them in batch would produce better compression ratios, saving more space.
  • It's difficult to remove playerdata on Linux when the playerdata file count gets too big (e.g. rm -f players/*.dat doesn't work anymore).
  • Trying to open a directory with thousands of files in it on Windows lags Explorer to death.
  • On some filesystems, the playerdata file count may reach or exceed the maximum files per directory limit.
  • Players' usernames are used as data keys, so player usernames are constrained by the valid characters which can appear in a filename (e.g. they can't contain / \ " . and so on).

However, it does have the following advantages which would be lost:

  • It's currently easy to delete a specific player's data. A tool would need to be provided to do this if LevelDB were used for storage.

Alternative methods

I've also considered SQLite3, but since PM4 already depends on LevelDB (and LevelDB supports binary data, unlike SQLite3), LevelDB appears to be the better option.

@dktapps dktapps added Category: Core Related to internal functionality Type: Enhancement Contributes features or other improvements to PocketMine-MP Performance labels Mar 14, 2021
@dktapps dktapps added this to the 5.0 milestone May 18, 2021
@dhdjSYS
Copy link

dhdjSYS commented Jul 31, 2021

After some testing it seems like leveldb won't support WSL 1 (maybe due to filesystem?). This may cause a compatibility issue.
However no one uses wsl1 anymore. That's the good news.

@dktapps
Copy link
Member Author

dktapps commented Aug 1, 2021

WSL is Microsoft's attempt to simulate Linux within Windows. The only reason to use it is for development. I personally don't use it and we don't lose much if it's not supported anyway.

@ghost
Copy link

ghost commented Sep 6, 2021

It's a great idea, but I recommend using the xuid as the key for the user data.

Player can change gametag. This is a big problem, because the player loses all his data

@ColinHDev
Copy link
Contributor

The XUID? What if xbox.auth is disabled?

@ghost
Copy link

ghost commented Sep 6, 2021

Oh, sorry..I hadn't thought of that.

Maybe add the ability to choose the type of key?

@ColinHDev
Copy link
Contributor

That would cause compatibility issues once the setting would be changed

@ColinHDev
Copy link
Contributor

For backwards compatibility we should stick with the name or at least use the UUID

@UnknownOre
Copy link
Contributor

UnknownOre commented Sep 6, 2021

use uuid, if xbox-auth is disabled use the name

@ColinHDev
Copy link
Contributor

If we would resolve #4076 we could just use uuids for both

@dktapps
Copy link
Member Author

dktapps commented Sep 6, 2021

This issue is not a debate about whether to use UUIDs, names or anything else as data keys. That's a topic for another discussion since it involves API changes as well as storage system changes.

@dktapps
Copy link
Member Author

dktapps commented Dec 25, 2024

Turns out this was a really bad idea, because LevelDB is really poorly suited to storing any kind of large data. The compactions and subsequent key sorting cause lots of unwanted I/O. We see this issue in large worlds in PM4 and up too (see #6580). This is compounded by the fact that LevelDB stores values in-line next to keys, so sorting keys also entails moving (potentially very large) blob data around.

To solve some of the issues mentioned here about player identification, we could use a LevelDB to store a simple map like:

  • player name -> .dat file name
  • UUID -> .dat file name
  • XUID -> .dat file name

This would be very light on data, require minimal I/O, and solve the problem around players' usernames being restricted by filename allowed characters, as well as allowing various other changes like identifying playerdata by UUID or XUID.

If we want to explore putting playerdata into a DB in the future to save space and get around other filesystem limitations, an unordered K/V database would be preferred, or something like RocksDB's BlobDB which stores values separately from keys to minimize I/O costs of sorting keys.

@dktapps dktapps closed this as completed Dec 25, 2024
@dktapps dktapps added the Resolution: Won't fix Will not be worked on label Dec 25, 2024
@dktapps dktapps closed this as not planned Won't fix, can't repro, duplicate, stale Dec 25, 2024
@dktapps dktapps moved this to Abandoned in Data & I/O improvements Dec 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Category: Core Related to internal functionality Performance Resolution: Won't fix Will not be worked on Type: Enhancement Contributes features or other improvements to PocketMine-MP
Projects
Status: Abandoned
Development

No branches or pull requests

4 participants