Giter Club home page Giter Club logo

Comments (41)

bearbin avatar bearbin commented on May 4, 2024

This is a very nice article discussing some different approaches to shrinking minecraft worlds in memory.

from cuberite.

madmaxoft avatar madmaxoft commented on May 4, 2024

That's a nice read, but unless they actually tried that approach in real life, I'm not gonna take their word for it that it works. I'm still more inclined towards slice-based sparsing.

from cuberite.

bearbin avatar bearbin commented on May 4, 2024

IDK, just thought it might be helpful 😄

from cuberite.

bearbin avatar bearbin commented on May 4, 2024

I think this should get a bit more love :)

This would be a huge advantage over the competition if it was implemented - and might drive more people to MCServer.

from cuberite.

madmaxoft avatar madmaxoft commented on May 4, 2024

I have re-read the article and still I believe the very first comment is right on the spot - the article over-estimates the iteration, and most of the costs are actually in random access. So I do believe that interval trees won't provide any performance gains, on the contrary, since most of the chunk-block access in MCS is random reads and writes, the performance would suffer, and the memory savings don't justify it.

However, there's still an option out there worth exploring, and that is the one thought up the in the forum: Divide each chunk vertically into 16 sections (same as the network protocol does) and only allocate those sections if they contain any nonzero data. Since most worlds generate at heightmap levels of 60 - 95 blocks, this would mean a 75% to 62% savings in RAM usage with almost minimal performance hit for the random access operations. For regular Nether worlds the RAM savings will be exactly 50 %, again with minimal performance penalty.

I would like to see this implemented so that the details stay mostly inside the cChunk class. However, with the chunk-based callbacks (cChunkDataCallback) currently used throughout the code, it might be a good idea to expose the 16 separate sections in those callbacks.

Also note that there's a server console command chunkstats that prints the statistics on memory used by chunks, this will have to be modified, too, to account for the underlying allocation changes.

from cuberite.

bearbin avatar bearbin commented on May 4, 2024

What about the "virtual array" mentioned - hashmaps - it's almost as fast as a flat array and can deliver slightly less memory than just removing empty slices.

from cuberite.

madmaxoft avatar madmaxoft commented on May 4, 2024

That's what we already do - it means splitting the entire world's data into 16x16 chunks and loading only the needed chunks.
The flat array, which might have confused you, is from the very old Minecraft Classic approach, when the world size was fixed at some 256x128x256 blocks (not sure about the exact sizes) and all the data was present in the memory all the time as one huge array.

from cuberite.

bearbin avatar bearbin commented on May 4, 2024

Anyway - the the sparsing option you just proposed is good enough 😃

from cuberite.

bennasar99 avatar bennasar99 commented on May 4, 2024

A 62% to 75% RAM saving? That needs to be implemented :D

from cuberite.

madmaxoft avatar madmaxoft commented on May 4, 2024

It means saving up to that much RAM, but it also means slightly lower performance - each GetBlock and SetBlock need to additionally check if the block is in the "loaded" section; SetBlock needs to create a new such section if it doesn't exist yet. It shouldn't be too problematic, though.

from cuberite.

worktycho avatar worktycho commented on May 4, 2024

Performance could be up to 4-5% worse. GetBlock at the moment is so small that any addition is significant and it is called so often that it contributes to 2-3% of running time in my profiles.

from cuberite.

madmaxoft avatar madmaxoft commented on May 4, 2024

You can't really say, because it's an extra condition, and conditions are always unpredictable performance-wise. Especially for architectures that have branch-predictions.

from cuberite.

bennasar99 avatar bennasar99 commented on May 4, 2024

Then, you could make it configurable. I would reduce performance on my server for chunk compression.

from cuberite.

madmaxoft avatar madmaxoft commented on May 4, 2024

Configurable means even more conditions - "check if it's enabled, then ..."

from cuberite.

madmaxoft avatar madmaxoft commented on May 4, 2024

I don't think there's any better way of testing this other than actually implementing it.

from cuberite.

madmaxoft avatar madmaxoft commented on May 4, 2024

But so far I don't think the performance hit would be any significant.

from cuberite.

bennasar99 avatar bennasar99 commented on May 4, 2024

Then implement it :D

from cuberite.

bennasar99 avatar bennasar99 commented on May 4, 2024

Nope, because MCServer performs very well right now.
Can't say the same about ram use, it could be less.

from cuberite.

worktycho avatar worktycho commented on May 4, 2024

That's why I said up to - implying that it could be 0%. I just wanted to point out that a tiny change to GetBlock can have a relativity massive effect on overall performance

from cuberite.

bearbin avatar bearbin commented on May 4, 2024

However, 5% less chunks per cpu is great if we can have double (or more) the chunks per ram.

from cuberite.

bennasar99 avatar bennasar99 commented on May 4, 2024

Common tiger! :P

from cuberite.

tigerw avatar tigerw commented on May 4, 2024

Could someone examine the chunkysparsing branch and tell me how bad the code is? It currently compresses only blocktypes and uses the 16-section selective allocation approach suggested by xoft.

Unscientific benchmarks report as follows:

With sparsing Without sparsing
Startup 1 (ms) 1884 1366
Startup 2 (ms) 1588 1194
Startup 3 (ms) 1627 1303
Average (ms) 1699.6 1687.6
Memory Usage (MB) 79 95

Savings/slowdown will probably vary with worlds.

from cuberite.

madmaxoft avatar madmaxoft commented on May 4, 2024

The sparsing should have saved much more memory. Without looking at the code I'd say there's something wrong :)

from cuberite.

tigerw avatar tigerw commented on May 4, 2024

Only blocktypes are compressed as of yet, so not nibbletypes; does that make up for it?

from cuberite.

madmaxoft avatar madmaxoft commented on May 4, 2024

If you're compressing only some data, then you're doing it wrong. You should have a structure containing the entire data for a 16x16x16 block area; these structures should either be present or NULL (full of air, not allocated)

from cuberite.

tigerw avatar tigerw commented on May 4, 2024
With Sparsing
S1: 2005
S2: 1344
S3: 1761
Avg (ms): 1703.3
Mem (mb): 63

New data following recent nibble compression changes.

from cuberite.

bearbin avatar bearbin commented on May 4, 2024

That's better, but I think the usage should be even lower really.

from cuberite.

bennasar99 avatar bennasar99 commented on May 4, 2024

From 95 to 63 is a great memory saving.

from cuberite.

bearbin avatar bearbin commented on May 4, 2024

I'm not saying it isn't a great saving, just more would be expected. You
are losing about 2/3 of the data (avg chunk height is about 80 blocks
compared to 256 max) but only removing 1/3 of the ram..

from cuberite.

tigerw avatar tigerw commented on May 4, 2024

Okay okay I'm not xoft...

Skylight and blocklight arrays aren't compressed yet.

from cuberite.

tigerw avatar tigerw commented on May 4, 2024

For skylight, I'm presuming that most blocks would be 15, not 0, right?

Also, I can't find anything in LightingThread that would set skylight to anything less, because it seems that the whole chunk is populated with 15 without checks for block solidity, and therefore skylight doesn't spread or decrease, even to blocks without a view of the sky.

from cuberite.

madmaxoft avatar madmaxoft commented on May 4, 2024

I'm telling you, if you're compressing them separately, you're doing it wrong.

Have a look at how the protocol handles sending chunks over, that should inspire you on how you should do it.

from cuberite.

tigerw avatar tigerw commented on May 4, 2024

From what I can see, doesn't cProtocol17x::SendChunkData() always serialise with cChunkDataSerialiser::Serialise(cChunkDataSerialiser::RELEASE_1_3_2), which sets the 'ground-up-continuous' flag to 'whole chunk sent' (i.e. not split up into 16 sections and sent selectively)?

Also, isn't putting blocktype, meta, light, and skylight all into one vector bad for code readability?

from cuberite.

madmaxoft avatar madmaxoft commented on May 4, 2024

The chunk data serializer does that because it doesn't have the sections pre-calculated and calculating them would cost more CPU than sending just everything. IF the serializer received the data already sectionized, it could send them like that.

You won't be putting all of the data into one vector. You should be using something like this:

struct sChunkSectionData
{
  BLOCKTYPE m_BlockTypes[16 * 16 * 16];
  NIBBLETYPE m_BlockMetas[16 * 16 * 8];
  NIBBLETYPE m_BlockSkyLight[16 * 16 * 8];
  NIBBLETYPE m_BlockBlockLight[16 * 16 * 8];
} ;
typedef sChunkSectionData * pChunkSectionData;

class cChunk
{
  ...
  pChunkSectionData Sections[16];  // Either NULL or valid section
} ;

from cuberite.

tigerw avatar tigerw commented on May 4, 2024
With Sparsing
S1: 1061
S2: 1288
S3: 1121
Avg (ms): 1156.6
Mem (mb): 34

Changes with blocklight and skylight compression.

from cuberite.

tigerw avatar tigerw commented on May 4, 2024

xoft, are you sure using C arrays with section splitting will have significant benefits over using vectors and not allocating until we reach an Index that is nonzero (changed compression algorithm recently)? I hope I don't have to rewrite everything...

from cuberite.

madmaxoft avatar madmaxoft commented on May 4, 2024

I'm not yet sure about this. My solution is better on the CPU side - no reallocations, minimal heap fragmentation, possibility to write a custom specific allocator. Your solution might allocate the memory more tightly and might be a bit easier to implement at the start. I guess I'll have to finally look at your code :P

Also with my solution it would be possible (although probably won't be done) to further compress Nether chunks - they will have many sections full of air in the middle of the chunk.

from cuberite.

archshift avatar archshift commented on May 4, 2024

Is this fixed by #863?

from cuberite.

worktycho avatar worktycho commented on May 4, 2024

No, #863 is temporary until we can actually get #956 done.

from cuberite.

NiLSPACE avatar NiLSPACE commented on May 4, 2024

Isn't this fixed now?

from cuberite.

bearbin avatar bearbin commented on May 4, 2024

Yes.

from cuberite.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.