0

I'm developing an emulator for a game. I have an object named "Map", which contains the map's id, and other various information about it. The game contains a lot of map objects (about 10,000). The data is located inside a SQL table, so I'm using that to load it.

I have a class named CachedMaps which inherits from a KeyedCollection of int and map. The identifier is the map's id. Unfortunately, it takes about 5 seconds to load all the maps.

Not all the maps will be visited, anyway. My friend suggested that I would use "lazy loading", I'm not sure how to do it - like, load the map's data or object only when a user enters it. How is it possible? Thank you.

public class CachedMaps : KeyedCollection<int, Map>
{
    public CachedMaps()
        : base()
    {
        // The loading code.
        // this.Add(new Map(....));
    }
}
Pragmateek
  • 13,174
  • 9
  • 74
  • 108

3 Answers3

2

You should use the Lazy generic class whose purpose is exactly that.

Use example from MSDN : (the "large object" would be your map):

lazyLargeObject = new Lazy<LargeObject>(() => 
{
    LargeObject large = new LargeObject(Thread.CurrentThread.ManagedThreadId);
    // Perform additional initialization here. 
    return large;
});
quantdev
  • 23,517
  • 5
  • 55
  • 88
  • I'm sorry, but where exactly would I use that code? –  May 17 '14 at 14:14
  • you instanciate a new Lazy instead of your nw Map, and use the Value property of th lazy to access your map, when your need it. – quantdev May 17 '14 at 14:18
  • `var lazyCachedMaps = new Lazy();` then when you want to access these maps use `var cachedMaps = lazyCachedMaps.Value;`. Check out the [constructor docs](http://msdn.microsoft.com/query/dev12.query?appId=Dev12IDEF1&l=EN-US&k=k(System.Lazy`1.%23ctor);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5);k(DevLang-csharp)&rd=true) to see what kind of options you need to construct this Lazy type with, if any. – Mike May 17 '14 at 14:22
  • @karim Do you mind showing me a full example of how it's used? Thanks. –  May 17 '14 at 14:22
1

Im my mind, the best way for you IF you're ok with making a call to the DB to load a map, would be a physical lazy load (or that's what I call it).

The concept here is that on first load, you only get the information you need for the user to CHOOSE a map... how you do that is up to you... a drop-down with the map names and IDs... a list of small screenshots (I'm thinking game here) with associated ID.

Then, ONLY once the user selects a map does it go and get the full map information from the DB. As well, since you mention that the object is large, I I would only cache the list of map identifiers for the "select a map" part, and NOT the maps themselves... for this simple scenario: What if I am testing your stuff, and run the ultimate scenario which is to load ALL maps. If all of these get cached, you'll run out of memory.

That's how i would do it anyway...

MaxOvrdrv
  • 1,780
  • 17
  • 32
0

Just create a class containing a Dictionary, not one overriding a KeyedCollection:

public class CachedMaps
{
    private readonly Dictionary<int, Map> _maps = new Dictionary<int, Map>();

    public Map GetMap(int mapId)
    {
        if (!this._maps.ContainsKey(mapId))
        {
            this._maps[mapId] = this.Add(new Map(....));
        }
        return this._maps[mapId];
    }
}

Now maps are loaded on demand and then cached.

Gert Arnold
  • 105,341
  • 31
  • 202
  • 291