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

Optimize memory usage of liblcf #253

Open
mateofio opened this issue Oct 5, 2018 · 6 comments
Open

Optimize memory usage of liblcf #253

mateofio opened this issue Oct 5, 2018 · 6 comments

Comments

@mateofio
Copy link
Contributor

mateofio commented Oct 5, 2018

liblcf uses a lot of memory.

I wrote a program that reads RPG_RT.ldb and then exits. I measured it's memory usage with valgrind massif.

Here are some quick stats:

Game RPG_RT.ldb Loaded Database Mem Usage overhead
Heros Realm 27 MB 300 MB 11x
HH3 16M 136.4 MB 8.3x
BloodmoonEnt. & Hangman 88KB 543KB 6x
Fate Hunter Orleon 368KB 2.1MB 6x
First Fantasy 1.3MB 5.2MB 4x
MKs Quest 3 (Demo) 2.3MB 11.1MB 4.8x
Siara 172KB 1.2MB 7x
@carstene1ns
Copy link
Member

Heros Realm has the biggest database we know of so far, so is a good candidate for testing. We have tried to optimize this a bit before, but never went far. I suspect the usage of STL (i.e. std::string) and generally template code may have some overhead.

@mateofio
Copy link
Contributor Author

mateofio commented Oct 31, 2018

Here is some data on the breakup per section of the database. I generated this by hacking liblcf to only load a single database chunk.

Game Actor Skills Items Enemies Troops Terrains Attributes States Animations Chipsets Terms System Switches Variables CommonEvents Version CommonEventD2 CommonEventD3 BattleCommands Classes ClassD1 BattlerAnimations
HH3 201.8KB 454.5KB 1MB 203.3KB 121.6MB 130.7KB 120.8KB 203KB 1.9MB 161.8KB 125.6KB 121.8KB 199.7KB 177.4KB 6.2MB 118.6KB 118.6KB 118.6KB 118.6KB 118.6KB 118.6KB 118.6KB
HeroesRealm 158.2KB 577KB 507KB 328.4KB 294.6MB 132.6KB 120.7KB 134.7KB 2.4MB 130.4KB 125.6KB 121.8KB 205.9KB 136.3KB 3.2MB 118.6KB 118.6KB 118.6KB 120.9KB 224.1KB 118.6KB 415.7KB
Violated Heroine 243.1 215KB 2.2MB 179.6KB 2.4MB 132.3KB 120.6KB 130.9KB 2.3MB 349.8KB 125.9KB 121.8KB 245.6KB 342.6KB 68.5MB 118.6KB 116.8KB 118.6KB 118.6KB 118.6KB 118.6KB 118.6KB

@mateofio
Copy link
Contributor Author

If I remove EventCommand::string by making it static, HH3 troop usage goes from 121.6MB to 69.8MB which is a 42% savings in memory.

On my amd64 linux machine, sizeof(EventCommand) == 64 and sizeof(std::string) == 32.

From this we can conclude that sizeof(EventCommand) is paramount. We need to make this structure as small as possible.

Furthermore, C++11 std::string is not optimized for us. std::string uses a small buffer optimization to store small strings inline without allocating memory. The problem is we have a lot of smaller or empty strings, but all of them consume 32 bytes.

Some kind of replacement for std::string would likely get us large memory savings all around.

@mateofio
Copy link
Contributor Author

mateofio commented Oct 31, 2018

Here is a WIP branch that implements an RPG::String and uses it for EventCommands::string. This string type stores a single pointer and behaves like a dynamically allocated const char*.

https://github.com/fmatthew5876/liblcf/tree/string

With this, sizeof(EventCommand) goes from 64 down to 40.

With this branch:

Game Master LDB Mem branch LDB Mem Savings
HH3 136.4MB 94.1MB 31%
Heroes Realm 300MB 202.3MB 33%
Violated Heroine 75.9MB 54.8MB 28%

@mateofio
Copy link
Contributor Author

mateofio commented Oct 31, 2018

One more test before bed. Here is liblcf master build with -D_GLIBCXX_USE_CXX11_ABI=0. This is effectively like using my RPG::String everywhere. This macro enables the old pre-C++11 std::string which used copy on write. In this version, sizeof(EventCommand) == 40.

Game LDB mem usage Savings
HH3 97.3MB 29%
Heros Realm 205.3MB 32%
Violated Heroine 58.1MB 23%

Interestingly, using this string everywhere actually increases memory usage compared to using it only in EventCommand.

@Ghabry
Copy link
Member

Ghabry commented Oct 31, 2018

Interesting savings you have there just by replacing one class, wow.

As you have my test set of game files now:
I'm curious if there is any other game which has a high LDB-memory usage that is not caused by event commands which is worth taking a look at.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

4 participants