Electroblob's Wizardry

Electroblob's Wizardry

18M Downloads

Bookshelf eating too much RAM

GodMorduk opened this issue ยท 3 comments

commented

Minecraft version: 1.12.2
Wizardry version: 4.3.4
Environment: Singleplayer

Issue details: bookshelf model eating 32mb of retained heap and got a lot of int[] objects. It is much for a single block, entire mod takes ~40mb of memory, so it doesn't seems as it should be.

Other mods involved: nothing I can identify. I don't place bookshelf in world, its just straight after loading heap dump.

image

Not sure I'm getting it correctly, but it seems that somehow it stores all possible book variants in memory? My Java skills are not appropriate for such problem, but hope it somehow helps.

image

commented

Interesting, I can't say I've noticed a performance impact. I notice that each BakedModelBookshelf has a different object assigned to its books field, I can't remember if this was intended but it shouldn't be necessary since all bookshelves share the same book models. Multiply this by 6 wood variants and 4 orientations and that's a lot of book models!

Here is the code that bakes the bookshelf models:

IModel bookshelfModel = ModelLoaderRegistry.getModel(bookshelfModelLocation);
// I don't know why default state works here (surely it ought to be the state param?), but it works so who cares
IBakedModel bookshelf = bookshelfModel.bake(bookshelfModel.getDefaultState(), format, bakedTextureGetter);
ImmutableList<ResourceLocation> textures = BlockBookshelf.getBookTextures();
IBakedModel[][] books = new IBakedModel[textures.size()][BlockBookshelf.SLOT_COUNT];
for(int i = 0; i < textures.size(); i++){
ImmutableMap<String, String> retexturer = ImmutableMap.of("books", textures.get(i).toString());
for(int j = 0; j < BlockBookshelf.SLOT_COUNT; j++){
IModel bookModel = ModelLoaderRegistry.getModel(new ModelResourceLocation(bookModelLocations.get(j), variant)).retexture(retexturer);
books[i][j] = bookModel.bake(bookModel.getDefaultState(), format, bakedTextureGetter); // Same here!
}
}
// To clarify: the whole point of doing this was to avoid having to bake 4 * 2^12 models per bookshelf type
// Therefore we have to have a baked bookshelf model that's kind of dynamic
return new BakedModelBookshelf(bookshelf, books);

It may be that I mistakenly assumed that IModel#bake(...) retrieves the existing baked model if it already exists, when in fact it must be making a new one each time that code is called (once for each bookshelf and orientation). I will see if there is a method for retrieving existing baked models instead, that might work.

commented

Maybe an config option to create only one "generic" bookshelf (or turn off some) would also help. I don't think everyone needs 6 variants, so there would be only 4, not 24 models.

Also why do you have a model for each direction? As I've seen, blockstates can handle it.

commented

Maybe an config option to create only one "generic" bookshelf (or turn off some) would also help. I don't think everyone needs 6 variants, so there would be only 4, not 24 models.

There is no reason why the game can't handle an arbitrary number of bookshelf types without much performance impact if done correctly. I would much rather fix the root cause of the problem rather than cover it up by removing features.

Also why do you have a model for each direction? As I've seen, blockstates can handle it.

I don't. There is only one model file for each bookshelf type, but the way the model system works is it generates one 'baked' model for each blockstate when the game loads. That's what all those objects are in the screenshot you posted.

Anyway, the point is not that there are too many bookshelf models, the problem is that it seems to be creating separate baked models for the books (not the bookshelf) in each type of bookshelf even though they are always the same. I just need to make it reuse the book models it has already generated.