{"action":"created","issue":{"url":"https://api.github.com/repos/jashkenas/backbone/issues/3858","labels_url":"https://api.github.com/repos/jashkenas/backbone/issues/3858/labels{/name}","comments_url":"https://api.github.com/repos/jashkenas/backbone/issues/3858/comments","events_url":"https://api.github.com/repos/jashkenas/backbone/issues/3858/events","html_url":"https://github.com/jashkenas/backbone/issues/3858","id":117088908,"number":3858,"title":"Subcollection memory leak (single model, multiple collections)","user":{"login":"TalonTR","id":15647922,"avatar_url":"https://avatars.githubusercontent.com/u/15647922?v=3","gravatar_id":"","url":"https://api.github.com/users/TalonTR","html_url":"https://github.com/TalonTR","followers_url":"https://api.github.com/users/TalonTR/followers","following_url":"https://api.github.com/users/TalonTR/following{/other_user}","gists_url":"https://api.github.com/users/TalonTR/gists{/gist_id}","starred_url":"https://api.github.com/users/TalonTR/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/TalonTR/subscriptions","organizations_url":"https://api.github.com/users/TalonTR/orgs","repos_url":"https://api.github.com/users/TalonTR/repos","events_url":"https://api.github.com/users/TalonTR/events{/privacy}","received_events_url":"https://api.github.com/users/TalonTR/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/jashkenas/backbone/labels/question","name":"question","color":"eb70b2"}],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":4,"created_at":"2015-11-16T10:03:24Z","updated_at":"2015-11-16T16:29:51Z","closed_at":"2015-11-16T15:19:39Z","body":"When adding a single Backbone.Model to multiple Backbone.Collections, each collection adds its own event listener to the added model (in _addReference). This reference prevents any collection to be garbage collected until every single model is explicitly removed from this collection. \r\n\r\nOur application depends on creating many temporary collections (from grouping or filtering results) to re-use extended collection methods on these results, containing already existing models from base collections. \r\nWe'd like to see these temporary collections garbage collected, once their reference gets discarded (via delete or leaving the scope). Instead we're aggregating references to every single temporary collection within every model, preventing them from ever getting discarded as long as the model is alive. \r\n\r\nSolving this problem by calling .reset() on every temporary collection and thereby removing the event listeners would be a major inconvenience. Is there any BB concept enabling us to use temporary backbone collections without forcing us to cleanup by ourselves?\r\n\r\nHere is a jsFiddle demonstrating the issue: http://jsfiddle.net/yf2t8w98/1/\r\nWatching the debugger timeline while running the loop you'll see something like that: \r\n\r\n![bb1](https://cloud.githubusercontent.com/assets/15647922/11179088/451b0e5e-8c51-11e5-812f-6c25024560c8.png)\r\n"},"comment":{"url":"https://api.github.com/repos/jashkenas/backbone/issues/comments/157088799","html_url":"https://github.com/jashkenas/backbone/issues/3858#issuecomment-157088799","issue_url":"https://api.github.com/repos/jashkenas/backbone/issues/3858","id":157088799,"user":{"login":"TalonTR","id":15647922,"avatar_url":"https://avatars.githubusercontent.com/u/15647922?v=3","gravatar_id":"","url":"https://api.github.com/users/TalonTR","html_url":"https://github.com/TalonTR","followers_url":"https://api.github.com/users/TalonTR/followers","following_url":"https://api.github.com/users/TalonTR/following{/other_user}","gists_url":"https://api.github.com/users/TalonTR/gists{/gist_id}","starred_url":"https://api.github.com/users/TalonTR/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/TalonTR/subscriptions","organizations_url":"https://api.github.com/users/TalonTR/orgs","repos_url":"https://api.github.com/users/TalonTR/repos","events_url":"https://api.github.com/users/TalonTR/events{/privacy}","received_events_url":"https://api.github.com/users/TalonTR/received_events","type":"User","site_admin":false},"created_at":"2015-11-16T16:29:51Z","updated_at":"2015-11-16T16:29:51Z","body":"Thanks @jridgewell for your answer. Unfortunately this doesn't provide the insight i was looking for. A non empty collection.models array is no reason for a collection not to get garbage collected, if there's no reference left:\r\n\r\n```    \r\nvar single_collection = new Backbone.Collection();\r\nfor (var i = 0; i < 10000; i++) {\r\n    single_collection.add( {} );\r\n}\r\ndelete single_collection;\r\n```\r\n\r\nThe last line removes the last existing reference to _single_collection_ , which then gets garbage collected, along with all its models. Thats expected behavior.\r\n\r\nCan you do me the favor and take a second look at the fiddle? What we're doing is adding the same model to many collections, which then instantly get discarded:\r\n```    \r\nfor (var i = 0; i < 10000; i++) {\r\n        \r\n    var tmp_collection = new Backbone.Collection();\r\n    tmp_collection.add(single_model);\r\n    \t\r\n    delete tmp_collection;\r\n}\r\n```\r\n\r\nSince _single_model_ is already a Backbone.Model, there is at no time more then one model within our heap. \r\n\r\nAfter the delete command there is no reference to _tmp_collection_ left, leaving it to be removed at the next garbage collection cycle - even if the collections _.model_ array is not emtpy at that point.\r\n\r\nThe memory buildup we see is because none of those _tmp_collection_ collections is ever really discarded, because they all add themselves to single_model.events - hence the console.log(single_model._events); at the end of the fiddle, which outputs:\r\n\r\n```\r\nObject {all: Array[10000]}\r\n```\r\n\r\nEven without any variable pointing to any tmp_collection ever created the garbage collector can't discard these collections because of those _events entries.\r\n\r\nThanks in advance for your patience."}}