{ "id": "80604", "key": "TIMOB-5361", "fields": { "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false }, "project": { "id": "10153", "key": "TIMOB", "name": "Titanium SDK/CLI", "projectCategory": { "id": "10100", "description": "Titanium and related SDKs used in application development", "name": "Client" } }, "fixVersions": [ { "id": "12080", "description": "", "name": "Sprint 2011-40", "archived": true, "released": true, "releaseDate": "2011-10-10" }, { "id": "11331", "description": "", "name": "Release 1.8.0", "archived": true, "released": true, "releaseDate": "2011-10-31" } ], "resolution": { "id": "1", "description": "A fix for this issue is checked into the tree and tested.", "name": "Fixed" }, "resolutiondate": "2011-11-03T15:09:33.000+0000", "created": "2011-09-26T10:13:40.000+0000", "priority": { "name": "High", "id": "2" }, "labels": [ "branch-5062" ], "versions": [ { "id": "11331", "description": "", "name": "Release 1.8.0", "archived": true, "released": true, "releaseDate": "2011-10-31" } ], "issuelinks": [ { "id": "13065", "type": { "id": "10003", "name": "Relates", "inward": "relates to", "outward": "relates to" }, "outwardIssue": { "id": "80452", "key": "TIMOB-5326", "fields": { "summary": "TiUITableView's \"make sure text field is visible\" EXC_BAD_ACCESS when Closing", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "priority": { "name": "High", "id": "2" }, "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false } } } }, { "id": "12844", "type": { "id": "10003", "name": "Relates", "inward": "relates to", "outward": "relates to" }, "inwardIssue": { "id": "80650", "key": "TIMOB-5380", "fields": { "summary": "Medtronic memory leaks (HTTP, suspend/resume, row reload, etc.)", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "priority": { "name": "Critical", "id": "1" }, "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false } } } }, { "id": "12833", "type": { "id": "10003", "name": "Relates", "inward": "relates to", "outward": "relates to" }, "inwardIssue": { "id": "80624", "key": "TIMOB-5376", "fields": { "summary": "Runloop modes during tracking events need to be reviewed.", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "priority": { "name": "Low", "id": "4" }, "issuetype": { "id": "7", "description": "gh.issue.story.desc", "name": "Story", "subtask": false } } } } ], "assignee": { "name": "stephentramer", "key": "stephentramer", "displayName": "Stephen Tramer", "active": true, "timeZone": "America/Los_Angeles" }, "updated": "2014-06-19T12:46:19.000+0000", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "components": [ { "id": "10206", "name": "iOS", "description": "iOS Platform" } ], "description": "h1. Problem\r\nWhen scrolling a table view, memory rapidly diminishes until you stop scrolling. Once you stop scrolling AND LIFT UP YOUR FINGER the memory releases.\r\n\r\nh2. How To Reproduce\r\n\r\n* Drop the following in an app.js\r\n* Scroll down and watch the memory fall\r\n* Touch and hold down with your finger to interrupt the table's deceleration and freeze it in place (figuratively speaking)\r\n* Watch the memory stay where it is\r\n* Let go with your finger\r\n* Watch the memory go back up\r\n\r\n{code:title=app.js}\r\nvar PLEASE_BLEED_MEMORY = true;\r\nvar win = Ti.UI.createWindow();\r\n\r\nvar rows = [];\r\nfor (var i = 0; i < 2000; i++) {\r\n var row = Ti.UI.createTableViewRow();\r\n row.add(row.label = Ti.UI.createLabel());\r\n if (PLEASE_BLEED_MEMORY) {\r\n row.label.text = 'blood and guts MU HA HA HA';\r\n }\r\n rows.push(row); \r\n}\r\nwin.add(Ti.UI.createTableView({ data: rows, bottom: 30 }));\r\n\r\nwin.add(win.freeMemory = Ti.UI.createLabel({\r\n text: 'Free Memory: Loading...', textAlign: 'center',\r\n bottom: 0, height: 30, color: '#fff', backgroundColor: '#000'\r\n}));\r\nsetInterval(function() {\r\n win.freeMemory.text = 'Free Memory: ' + Ti.Platform.availableMemory;\r\n}, 500);\r\n\r\nwin.open();\r\n{code}", "attachment": [], "flagged": false, "summary": "Table View Scroll Extreme Garbage Collection Starvation", "creator": { "name": "dtoth", "key": "dtoth", "displayName": "Dawson Toth", "active": true, "timeZone": "America/New_York" }, "subtasks": [], "reporter": { "name": "dtoth", "key": "dtoth", "displayName": "Dawson Toth", "active": true, "timeZone": "America/New_York" }, "environment": null, "comment": { "comments": [ { "id": "166960", "author": { "name": "stephentramer", "key": "stephentramer", "displayName": "Stephen Tramer", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Issue is likely:\r\n\r\nTiUITableviewRowProxy : DeepScanForProxyOfViewContainingPoint().\r\n\r\nThe issue here is that as part of the fast enumeration, [targetView subviews] is (possibly) called multiple times in a row, on the main thread, which cannot autorelease as long as presses are ongoing. We need some judicious use of autorelease pools in our hit detection (and to make sure we don't call this method more than once per scan anyway).", "updateAuthor": { "name": "stephentramer", "key": "stephentramer", "displayName": "Stephen Tramer", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-09-26T10:18:42.000+0000", "updated": "2011-09-26T10:18:42.000+0000" }, { "id": "166973", "author": { "name": "dtoth", "key": "dtoth", "displayName": "Dawson Toth", "active": true, "timeZone": "America/New_York" }, "body": "I have isolated this down to TiViewProxy.m's line 1025 (probably 1025...):\r\n\r\n[[view retain] performSelector:@selector(autorelease) withObject:nil afterDelay:0.5];\r\n\r\nIf I comment this out, the memory doesn't rapidly drop.", "updateAuthor": { "name": "dtoth", "key": "dtoth", "displayName": "Dawson Toth", "active": true, "timeZone": "America/New_York" }, "created": "2011-09-26T11:11:15.000+0000", "updated": "2011-09-26T11:29:49.000+0000" }, { "id": "166980", "author": { "name": "dtoth", "key": "dtoth", "displayName": "Dawson Toth", "active": true, "timeZone": "America/New_York" }, "body": "Introduced by [TIMOB-5326].", "updateAuthor": { "name": "dtoth", "key": "dtoth", "displayName": "Dawson Toth", "active": true, "timeZone": "America/New_York" }, "created": "2011-09-26T11:42:11.000+0000", "updated": "2011-09-26T11:42:11.000+0000" }, { "id": "166990", "author": { "name": "blainhamon", "key": "blainhamon", "displayName": "Blain Hamon", "active": true, "timeZone": "America/Los_Angeles" }, "body": "D'oh. I should have checked comments earlier. I've arrived to the same agreement, and it's well explained in the performSelector:...:afterDelay:'s docs-\r\n\r\n\"The timer is configured to run in the default mode (NSDefaultRunLoopMode). When the timer fires, the thread attempts to dequeue the message from the run loop and perform the selector. It succeeds if the run loop is running and in the default mode; otherwise, the timer waits until the run loop is in the default mode.\"\r\n\r\nWhile the tableview is under finger, the run loop mode is tracking, not default. Thus, it all makes sense. The solution, however, hrm...", "updateAuthor": { "name": "blainhamon", "key": "blainhamon", "displayName": "Blain Hamon", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-09-26T12:53:24.000+0000", "updated": "2011-09-26T12:53:24.000+0000" }, { "id": "167059", "author": { "name": "dtoth", "key": "dtoth", "displayName": "Dawson Toth", "active": true, "timeZone": "America/New_York" }, "body": "While the fix does free up memory earlier, memory still fluctuates way more than it should. Let me quantify that:\n\n1. Use the app.js in the original report\n2. Memory began at 45mb\n3. Scroll to the bottom; notice the scrolling gets choppier and choppier\n4. Memory dropped from 45mb to 30mb\n5. Memory quickly jumps up to where it started\n\nNow comment out the delayed view autorelease, and perform the same test.\n\n1. Same app.js, only difference is no delayed view autorelease\n2. Memory began at 45mb\n3. Scroll to the bottom; scrolling does get choppy, but it does not \"skip\" as much as it did previously\n4. Memory dropped from 45mb to 42mb\n5. Memory quickly jumps up to where it started\n\nWhat I want to communicate is that the fix that was introduced for one, small scenario in [TIMOB-5326] has a big performance impact on the table view. The app that I am working on is very scroll heavy, and we need as much help as we can get. Our memory usage is already sensitive, and 15 mb swings aren't going to help us stay stable.", "updateAuthor": { "name": "dtoth", "key": "dtoth", "displayName": "Dawson Toth", "active": true, "timeZone": "America/New_York" }, "created": "2011-09-27T00:06:54.000+0000", "updated": "2011-09-27T00:06:54.000+0000" }, { "id": "167944", "author": { "name": "dtoth", "key": "dtoth", "displayName": "Dawson Toth", "active": true, "timeZone": "America/New_York" }, "body": "Based on experimentation in the customer's app, one way around this could be to add a method to TiViewProxy that doesn't delay the autorelease of the view. In situations where it is safe to do so and we need the performance, we could call this method instead:\r\n\r\nSuch as in TiUITableViewRowProxy.m, line 636:\r\n{code:title=TiUITableViewRowProxy.m}\r\n[child detachViewImmediately];\r\n{code}\r\n\r\nThe method would be the same as the existing detachView, but without the delayed autorelease:\r\n{code:title=TiViewProxy.m}\r\n-(void)detachViewImmediately\r\n{\r\n\t[destroyLock lock];\r\n\tif (view!=nil)\r\n\t{\r\n\t\t[self viewWillDetach];\r\n\t\tview.proxy = nil;\r\n\t\tif (self.modelDelegate!=nil && [self.modelDelegate respondsToSelector:@selector(detachProxy)])\r\n\t\t{\r\n\t\t\t[self.modelDelegate detachProxy];\r\n\t\t}\r\n\t\tself.modelDelegate = nil;\r\n\t\t[view removeFromSuperview];\r\n\t\tRELEASE_TO_NIL(view);\r\n\t\t[self viewDidDetach];\r\n\t}\r\n \r\n pthread_rwlock_rdlock(&childrenLock);\r\n [[self children] makeObjectsPerformSelector:@selector(detachView)];\r\n pthread_rwlock_unlock(&childrenLock);\r\n\t[destroyLock unlock];\r\n}\r\n{code}\r\n\r\nDeclare that in the TiViewProxy.h, and we should be good to go. Of course, y'all know the implications of this change way better than I do. I'm only basing this on behavior from one app.", "updateAuthor": { "name": "dtoth", "key": "dtoth", "displayName": "Dawson Toth", "active": true, "timeZone": "America/New_York" }, "created": "2011-10-04T13:59:25.000+0000", "updated": "2011-10-04T13:59:25.000+0000" }, { "id": "167995", "author": { "name": "stephentramer", "key": "stephentramer", "displayName": "Stephen Tramer", "active": true, "timeZone": "America/Los_Angeles" }, "body": "This issue was introduced by the 5326 fix, and so the associated bug should be re-tested and resolved in conjunction with this one.", "updateAuthor": { "name": "stephentramer", "key": "stephentramer", "displayName": "Stephen Tramer", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-10-05T03:43:34.000+0000", "updated": "2011-10-05T03:43:34.000+0000" }, { "id": "168168", "author": { "name": "avaghti", "key": "avaghti", "displayName": "Alan Vaghti", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Closing.\n\nFix verified on iPod running 4.3.3 with SDK 1.8.0.v20111006001414. Free memory stays stable throughout scrolling.", "updateAuthor": { "name": "avaghti", "key": "avaghti", "displayName": "Alan Vaghti", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-10-06T14:17:25.000+0000", "updated": "2011-10-06T14:17:25.000+0000" }, { "id": "171270", "author": { "name": "avaghti", "key": "avaghti", "displayName": "Alan Vaghti", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Reopening.\r\n\r\nIssue is reproducible in build 1.8.0.v20111101161253 with an iPod 4.3.3.\r\n\r\nFree memory starts at around 70, but as I scrolled down it went to less then 2.", "updateAuthor": { "name": "avaghti", "key": "avaghti", "displayName": "Alan Vaghti", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-11-02T15:07:55.000+0000", "updated": "2011-11-02T15:07:55.000+0000" }, { "id": "171407", "author": { "name": "rseagraves", "key": "rseagraves", "displayName": "Reggie Seagraves", "active": true, "timeZone": "America/Los_Angeles" }, "body": "This issue was resolved for a custom branch only and the test case does not apply to the 1.8 release. Should be reclosed as resolved.", "updateAuthor": { "name": "rseagraves", "key": "rseagraves", "displayName": "Reggie Seagraves", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-11-03T15:08:51.000+0000", "updated": "2011-11-03T15:08:51.000+0000" } ], "maxResults": 11, "total": 11, "startAt": 0 } } }