Skip to content
This repository has been archived by the owner on Apr 22, 2021. It is now read-only.

Garbage Collection #8

Open
anthonyshort opened this issue Jul 2, 2012 · 5 comments
Open

Garbage Collection #8

anthonyshort opened this issue Jul 2, 2012 · 5 comments
Labels

Comments

@anthonyshort
Copy link

I'm looking at implementing supermodel in an app I'm building. I cobbled together something similar before I found this. I was curious about garbage collection though.

In a single page app, let's say I'm looking at a task list, it's loaded in all the models and it's storing them in Task.all(). I navigate to another part of the application that also uses tasks. My choice at this point is to either reset Task or just leave the models in there. It seems like leaving them in there could result in large memory build-up. Task could store hundreds of unused models as the user continues to use the app.

Obviously there is some level of subjectivity with this and it's up to the developer to decide when it should clear the 'cache'. It would be nice if Supermodel could keep track of how many views are using a model and remove them on an interval. It's the only real way I could see it automatically cleaning up after itself and preventing large build up. Perhaps I'm over-thinking it or need to find a better solution for single-model-per-page.

@flippyhead
Copy link
Contributor

You're not over thinking this. We have this problem too and are actively thinking about how to address it.

@braddunbar
Copy link
Contributor

Hi @anthonyshort! Thanks for the question. As far as Supermodel goes, you can release models for garbage collection by removing them from the all() collections. Triggering "destroy" on a model will remove it from all collections, including Supermodel collections.

Garbage collection is definitely an issue here since we are keeping models around indefinitely (it's certainly not unique to Supermodel). I know of two ways to handle this:

  1. Trigger destroy on an as needed basis - Releasing some set of models, possibly all of them, can be done when navigating between views or after some pre-defined time interval. Deciding which models should be released can be somewhat problematic, but in general this strategy works well.
  2. Implement custom GC through ref counting or a similar strategy - I haven't personally used this technique, but it seems to have been successful at Soundcloud.

@anthonyshort
Copy link
Author

Ref counting wouldn't be too bad and it would be automatic.

I'm assuming a view/collection would announce that it's attaching itself a model and the model would keep track of how many objects are using it. An interval would check for models with a ref count of zero and remove them from the storage.

I originally had thought of doing this after seeing the Soundcloud article, but I wasn't sure if it would be a good long-term solution and could add a fair bit of complexity.

@mikepb
Copy link

mikepb commented Jul 3, 2012

I would recommend against using setInterval if using setTimeout and re-setting the timeout after it completes also works. setInterval can potentially hang the browser if the script takes too long to finish before the next interval fires.

You could do something like this for reference counting:

Model.prototype._refs = 0;

Model.prototype.ref = function() {
  this._refs++;
  return this;
};

Model.prototype.unref = function() {
  if (--this._refs <= 0) {
    _.each(this.constructor.supers(), function(s) {
      s.all().remove(this);
    }, this);
  }
  return this;
};

@anthonyshort
Copy link
Author

That will work well. Thanks. I'll probably integrate with that my disposal methods and use options to remove it from the cache. I'm using a modified version of Chaplin. They use the method dispose to remove a view/model/collection from memory.

model.dispose({
    removeFromCache:true
});

This way when switching between pages in the application I don't lose all my models (unless I want to).

// Keep the models in the cache, but dispose of the view
collectionView.dispose();

// Dispose the view and remove all models from the cache
collectionView.dispose({
    removeFromCache: true;
});

// Removes it from the cache, obviously.
model.destroy();

// Remove the view and remove the model from the cache.
itemView.dispose({
    removeFromCache: true
});

I like the idea of an opt-in approach so I know exactly when I'm removing them. This allows me to keep the models in between parts of my application if I want to. My base classes will automatically do this for me when calling certain methods but by default it will keep them in the cache.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

4 participants