Search Unity

Large Object - Better to access from disk? How do I tell?

Discussion in 'Scripting' started by Schneider21, Jul 26, 2016.

  1. Schneider21

    Schneider21

    Joined:
    Feb 6, 2014
    Posts:
    3,512
    I have an object that has nested objects in a hierarchy that goes something like this:
    Code (CSharp):
    1. - Quadrant
    2. -- Sectors[][]
    3. --- Systems[]
    4. ---- Planets[]
    5. ----- Moons[]
    Sectors is an array of 100x100, which gives me 10,000 sectors, ~55k systems, and ~440k planets. Most of the other properties are just ints, floats, a bunch of enums, and some strings.

    I'm focusing on mobile devices at the moment... Is it a bad idea to keep this object in memory throughout the course of the game? Should I be saving the object to disk after generating it and attempt to load and access elements from it as needed? Or am I worrying about nothing and should just handle it like any other object?

    How do I go about finding out how much memory this object is occupying?
     
  2. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    I would suggest looking into spatial partitioning based solely on the number of planets you have. There is very little reason to have that many objects in your scene unless you're implementing some complex physics simulations. Serialize the planets you can't see to disk and stream them in when you get within viewing range. You can use the built-in profiler to see memory usage and other analytical data.
     
  3. Schneider21

    Schneider21

    Joined:
    Feb 6, 2014
    Posts:
    3,512
    Sorry, I think I misrepresented what I'm doing.

    Planets exist only as instance members of my custom classes. They're not actual GameObjects in the scene. So each of the items in the hierarchy (Quadrant, Sector, StarSystem, Planet) are just custom classes, and I generate instances with various details at app initialization.

    My question is: Is it likely fine to just keep this object as a property of my App Manager class (kept in memory), or should I serialize and save it to disk, then access specific parts as needed (when loading data for a new sector)?

    Additionally, how can I determine how much memory this object collection is taking up so that I can make that determination myself to weigh it against the performance cost of accessing disk storage repeatedly?

    Edit for additional clarity: None of these classes are monobehaviors. They're all just data that I access to do other stuff with.
     
  4. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,702
    You can just add up the data type sizes using MSDN's Data Type Summary table. There's a cost to serializing both in terms of processing overhead and technical complexity. Once you know how much memory you're talking about, you can make a more informed decision about the costs and benefits of serializing.

    For example, your Sectors[100][100] will be 40,000 bytes. That's just for the object references to your Sector instances, not any other variables in the class.
     
    Schneider21 likes this.
  5. Schneider21

    Schneider21

    Joined:
    Feb 6, 2014
    Posts:
    3,512
    Awesome! Thanks, @TonyLi! Exactly what I needed!

    I'm using Moodkie's excellent Easy Save 2 for saving/serialization, so the complexity isn't so much the concern for me as the performance cost is. Though I don't want to get into premature optimization, I also want to just approach it the way that will make the most sense for how I should realistically approach it!

    Assuming I end up going with serializing and saving after generating, do you have any tips on how to access specific objects later on? Is it loading the entire object back into memory to grab the part I need, or if I'm saving it smartly, should I be able to load up only specific content?

    Off to do some math and figure out what I'm dealing with here. Thanks again!
     
  6. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,702
    It might not be an issue. Let's say the data for a moon or planet is:
    5 floats = 20 bytes
    10 ints = 20 bytes
    2 strings * 80 bytes each = 160 bytes
    TOTAL: 200 bytes

    5 moons/planet average = 5 * 200 = 1000 bytes

    10 planets/system average = 10 * 200 + 1000 (moons) = 3000 bytes

    10 systems/sector average = 30,000 bytes (~30 KB)

    10,000 sectors x 30 KB = 300,000 KB = ~300 MB

    So in this case if you can spare 300 MB then I'd say don't bother with serializing.


    Then again that might be too much for a mobile game. But a system is only 3 KB, which will load fast and not take much memory. I'd save each system under a separate ES2 key, such as "System_x_y_z" for Sectors[x][y].Systems[z]. This will make it really easy to load.
     
  7. Schneider21

    Schneider21

    Joined:
    Feb 6, 2014
    Posts:
    3,512
    It may be more dire than that. The page you linked was VB.NET. This page suggests a C# int is 32 bits, and from what I can tell, Unity enums' underlying type is always int (and I use a lot of those).

    This seems like the most sensible approach. I think even going back up one level and just saving each sector as its own data file and loading them as needed would be a good balance as well.

    I think I'll give this a shot. Again, really appreciate your input, as always.
     
  8. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,702
    Happy to help, even if my google-fu is weak today. Sorry about linking the wrong data type page. :)