{ "id": "94902", "key": "TIMOB-10363", "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": "13505", "description": "Release 3.0.0", "name": "Release 3.0.0", "archived": true, "released": true, "releaseDate": "2012-12-14" }, { "id": "14162", "description": "Release 3.1.0", "name": "Release 3.1.0", "archived": true, "released": true, "releaseDate": "2013-04-16" }, { "id": "14168", "description": "2012 Sprint 22 API", "name": "2012 Sprint 22 API", "archived": true, "released": true, "releaseDate": "2012-11-05" }, { "id": "14274", "description": "2012 Sprint 22", "name": "2012 Sprint 22", "archived": true, "released": true, "releaseDate": "2012-11-05" } ], "resolution": { "id": "1", "description": "A fix for this issue is checked into the tree and tested.", "name": "Fixed" }, "resolutiondate": "2012-10-30T21:35:44.000+0000", "created": "2012-07-11T03:07:05.000+0000", "priority": { "name": "High", "id": "2" }, "labels": [ "3.0.0beta2", "api" ], "versions": [ { "id": "13271", "description": "Release 2.1.0", "name": "Release 2.1.0", "archived": false, "released": true, "releaseDate": "2012-06-29" } ], "issuelinks": [], "assignee": { "name": "krowley", "key": "krowley", "displayName": "Karl Rowley", "active": true, "timeZone": "America/Los_Angeles" }, "updated": "2012-12-05T18:46:06.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": "10202", "name": "Android", "description": "Android Platform" } ], "description": "h2. The problem\r\n\r\nPicker's \"add\" method is very slow, when creating picker with 30 rows on tablet with Tegra2 processor, picker \"add\" method takes about 1.5 seconds to execute.\r\n\r\n\r\nThis greatly impacts Titanium's performance when there are more pickers with more that just a few options.\r\n\r\n\r\nh2. Test case\r\n\r\n\r\n{code}\r\n(function() {\r\n \r\n var win = Ti.UI.createWindow({\r\n \t\tbackgroundColor: '#000'\r\n });\r\n \r\n var data = [];\r\n \r\n var start = new Date();\r\n \r\n for (var i = 0; i < 30; ++i) {\r\n \t\tdata[i] = Ti.UI.createPickerRow({ title: 'Row ' + i });\r\n }\r\n \r\n Ti.API.info('Rows: ' + (new Date() - start));\r\n \r\n var picker = Ti.UI.createPicker();\r\n \r\n start = new Date();\r\n \r\n picker.add(data);\r\n \r\n Ti.API.info('Finished: ' + (new Date() - start));\r\n \r\n win.add(picker);\r\n \r\n win.open();\r\n \r\n})();\r\n{code}\r\n\r\n\r\n30 rows is really not big number, especially on powerful hardware. 1.5 seconds is a way too much. JS execution time (creation of array of picker's rows) is 14ms. Execution of \"add\" method should be similar to that value.", "attachment": [], "flagged": false, "summary": "Android: Picker \"add\" method is dead slow", "creator": { "name": "ivan.skugor", "key": "ivan.skugor", "displayName": "Ivan Skugor", "active": true, "timeZone": "Europe/Amsterdam" }, "subtasks": [], "reporter": { "name": "ivan.skugor", "key": "ivan.skugor", "displayName": "Ivan Skugor", "active": true, "timeZone": "Europe/Amsterdam" }, "environment": "* Titanium SDK version: 2.2.0 (07/09/12 15:21 82b62cd)\r\n* v8\r\n* Android 3.1\r\n* Thinkpad tablet\r\n* OSX Lion", "comment": { "comments": [ { "id": "209290", "author": { "name": "ivan.skugor", "key": "ivan.skugor", "displayName": "Ivan Skugor", "active": true, "timeZone": "Europe/Amsterdam" }, "body": "I have more info regarding this issue. If seems that slowdown exists only on startup.\r\n\r\n\r\nHere is updated test case:\r\n\r\n\r\n{code}\r\nvar j = 0;\r\n\r\n\r\nfunction create() {\r\n    \r\n   var win = Ti.UI.createWindow({\r\n        backgroundColor: '#000',\r\n\t\tnavBarHidden: true\r\n   });\r\n    \r\n   var data = [];\r\n    \r\n   var start = new Date();\r\n\r\n\tTi.API.info(j);\r\n    \r\n   for (var i = j; i < (j + 30); ++i) {\r\n        data.push(Ti.UI.createPickerRow({ title: 'Row ' + i }));\r\n   }\r\n    \r\n    Ti.API.info('Rows: ' + (new Date() - start));\r\n    \r\n   var picker = Ti.UI.createPicker();\r\n    \r\n   start = new Date();\r\n    \r\n   picker.add(data);\r\n    \r\n   Ti.API.info('Finished: ' + (new Date() - start));\r\n    \r\n   win.add(picker);\r\n\r\n\tj = j + 30;\r\n\r\n\twin.addEventListener('open', function() {\r\n\t\tTi.API.info('OPEN: ' + (new Date() - start));\r\n\t});\r\n\r\n\twin.addEventListener('click', function() {\r\n\t\tcreate();\r\n\t});\r\n    \r\n   win.open();\r\n    \r\n}\r\n\r\n\r\ncreate();\r\n{code}\r\n\r\n\r\nWhen app starts, execution time is 1.5s (and that number is greater with bigger number of pickers), but performance is satisfying when other windows are created (and that can be seen if window is clicked and new picker is generated).", "updateAuthor": { "name": "ivan.skugor", "key": "ivan.skugor", "displayName": "Ivan Skugor", "active": true, "timeZone": "Europe/Amsterdam" }, "created": "2012-07-25T02:55:53.000+0000", "updated": "2012-07-25T02:55:53.000+0000" }, { "id": "214672", "author": { "name": "pwang", "key": "pwang", "displayName": "Ping Wang", "active": true, "timeZone": "America/Los_Angeles" }, "body": "The original test case does not count the time correctly. When an app starts, a new activity is launched. After the activity is launched, it needs to go through three states - onCreate(), onStart() and onResume() before it is running. This process takes time. Therefore, the test code below is more accurate to count the time that the method picker.add() takes. It takes about 10ms.\r\n{code}\r\nvar win = Ti.UI.createWindow({\r\n\tbackgroundColor : '#000'\r\n});\r\n\r\nvar button = Ti.UI.createButton({\r\n\ttitle: 'Create picker with 30 rows'\r\n});\r\n\r\n\r\nbutton.addEventListener('click', function() {\r\n\r\n\tvar data = [];\r\n\t\r\n\tfor (var i = 0; i < 30; ++i) {\r\n\t\tdata[i] = Ti.UI.createPickerRow({\r\n\t\t\ttitle : 'Row ' + i\r\n\t\t});\r\n\t}\r\n\r\n\tvar picker = Ti.UI.createPicker({top: 50});\r\n\r\n\tvar start = new Date();\r\n\t\r\n\tpicker.add(data);\r\n\r\n\tTi.API.info('************* Finished: ' + (new Date() - start));\r\n\r\n\twin.add(picker);\r\n});\r\n\r\nwin.add(button);\r\n\r\nwin.open(); \r\n{code}", "updateAuthor": { "name": "pwang", "key": "pwang", "displayName": "Ping Wang", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2012-08-15T15:06:31.000+0000", "updated": "2012-08-15T15:06:31.000+0000" }, { "id": "214767", "author": { "name": "ivan.skugor", "key": "ivan.skugor", "displayName": "Ivan Skugor", "active": true, "timeZone": "Europe/Amsterdam" }, "body": "But if I change picker code with table view code result is:\r\n\r\n\r\n08-16 16:27:12.911: I/TiAPI(32075): Rows: 21\r\n08-16 16:27:12.941: I/TiAPI(32075): Finished: 26\r\n08-16 16:27:13.181: I/TiAPI(32075): OPEN: 271\r\n\r\nCompare that with picker results:\r\n\r\n08-16 16:14:46.871: I/TiAPI(31843): Rows: 20\r\n08-16 16:14:48.361: I/TiAPI(31843): Finished: 1479\r\n08-16 16:14:48.561: I/TiAPI(31843): OPEN: 1689\r\n\r\nThat's huge difference and I doubt that is normal (note that there is identical number of rows).\r\n\r\n\r\nAfter window in opened, there is no performance drop. This only happens when app lunches for the first time.\r\n\r\n\r\nHere is my code (table view part is commented):\r\n\r\n{code}\r\nvar j = 0;\r\n\r\nfunction create() {\r\n\tvar win = Ti.UI.createWindow({\r\n\t\tbackgroundColor: '#000',\r\n\t\tnavBarHidden: true\r\n\t});\r\n\tvar data = [];\r\n\tvar start = new Date();\r\n\r\n    Ti.API.info(j);\r\n\tfor (var i = j; i < (j + 30); ++i) {\r\n\t\tdata.push(Ti.UI.createPickerRow({ title: 'Row ' + i }));\r\n\t\t// data.push(Ti.UI.createTableViewRow({ title: 'Row ' + i, className: 'Row' }));\r\n\t}\r\n\tTi.API.info('Rows: ' + (new Date() - start));\r\n\tvar picker = Ti.UI.createPicker();\r\n\t// var table = Ti.UI.createTableView();\r\n\tstart = new Date();\r\n\tpicker.add(data);\r\n\t// table.setData(data);\r\n\tTi.API.info('Finished: ' + (new Date() - start));\r\n\twin.add(picker);\r\n\t// win.add(table);\r\n\tj = j + 30;\r\n\twin.addEventListener('open', function() {\r\n\t\tTi.API.info('OPEN: ' + (new Date() - start));\r\n\t});\r\n\twin.addEventListener('click', function() {\r\n\t\tcreate();\r\n\t});\r\n\twin.open(); \r\n}\r\n\r\ncreate();\r\n{code}", "updateAuthor": { "name": "ivan.skugor", "key": "ivan.skugor", "displayName": "Ivan Skugor", "active": true, "timeZone": "Europe/Amsterdam" }, "created": "2012-08-16T07:30:08.000+0000", "updated": "2012-08-16T07:30:08.000+0000" }, { "id": "215017", "author": { "name": "pwang", "key": "pwang", "displayName": "Ping Wang", "active": true, "timeZone": "America/Los_Angeles" }, "body": "picker.add() method needs to be done in the UI thread. The method sends a message to the message queue and UI thread will execute it as it comes out of the message queue. Therefore, if there are some other messages before this one, it will delay the execution of this method.\r\nI used the Android [Debug|http://developer.android.com/reference/android/os/Debug.html] class to generate the [traceview|http://developer.android.com/tools/debugging/debugging-tracing.html]. When the app launches for the first time, picker.add() method takes 64.269ms in total and it spends 60.147ms in sending and handling messages, which means it only takes 4.122ms to handle the \"add\" action. When the app is already launched(eg. the window is already opened), picker.add() method takes 19.317ms in total and it spends 16.358ms in sending and handling messages, which means it takes 2.959ms to handle the \"add\" action. Considering the possible fluctuations, those numbers tell us the picker.add() method is not slow. It's just because when the app launches for the first time, there are a lot of messages / actions waiting to be taken care of in the UI thread which delay the method.", "updateAuthor": { "name": "pwang", "key": "pwang", "displayName": "Ping Wang", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2012-08-17T15:00:57.000+0000", "updated": "2012-08-17T15:00:57.000+0000" }, { "id": "215117", "author": { "name": "ivan.skugor", "key": "ivan.skugor", "displayName": "Ivan Skugor", "active": true, "timeZone": "Europe/Amsterdam" }, "body": "OK, thanks. I don't understand Titanium internals so I cannot comment is that normal or not. But as Titanium developer I think it's not normal that app loads slowly because of picker with 30 rows. It's not logical that TableView loads a lot faster with same number of rows.\r\n\r\n\r\nHere is example with 5 picker with 30 rows.\r\n\r\n\r\n{code}\r\nfunction create() {\r\n\t\r\n    var win = Ti.UI.createWindow({\r\n        backgroundColor: '#000',\r\n\t\tlayout: 'vertical',\r\n        navBarHidden: true\r\n    });\r\n    \r\n    var start = new Date();\r\n\r\n\tfor (var j = 0; j < 5; ++j) {\r\n\t\tvar data = [];\r\n\t    for (var i = 0; i < 30; ++i) {\r\n\t        data.push(Ti.UI.createPickerRow({ title: 'Row ' + i }));\r\n\t        // data.push(Ti.UI.createTableViewRow({ title: 'Row ' + i, className: 'Row' }));\r\n\t    }\r\n\t    var picker = Ti.UI.createPicker();\r\n\t    // var table = Ti.UI.createTableView();\r\n\t    picker.add(data);\r\n\t    // table.setData(data);\r\n\t    win.add(picker);\r\n // win.add(table);\r\n\t}\r\n\r\n    \r\n    win.addEventListener('open', function() {\r\n        Ti.API.info('OPEN: ' + (new Date() - start));\r\n    });\r\n    win.addEventListener('click', function() {\r\n        create();\r\n    });\r\n    win.open(); \r\n}\r\n\r\ncreate();\r\n{code}\r\n\r\nIt takes 8 seconds to load application (same app with TableViews loads in 0.5 seconds)! IMO, that cannot be considered as normal or acceptable. Native app would load instantly.", "updateAuthor": { "name": "ivan.skugor", "key": "ivan.skugor", "displayName": "Ivan Skugor", "active": true, "timeZone": "Europe/Amsterdam" }, "created": "2012-08-20T04:48:35.000+0000", "updated": "2012-08-20T04:49:44.000+0000" }, { "id": "215283", "author": { "name": "ngupta", "key": "ngupta", "displayName": "Neeraj Gupta", "active": true, "timeZone": "America/Los_Angeles" }, "body": "I agree that it should not take 8 seconds in this scenario. We need to investigate this issue further.", "updateAuthor": { "name": "ngupta", "key": "ngupta", "displayName": "Neeraj Gupta", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2012-08-20T20:42:16.000+0000", "updated": "2012-08-20T20:42:16.000+0000" }, { "id": "218082", "author": { "name": "jbrackett", "key": "jbrackett", "displayName": "Josh", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Since I can't seem to find the vote button I'll comment that I'm also seeing this. We have two pickers with ~130 rows and they each take 9-10 seconds each the first time the app loads up. Subsequently they take 200-300ms each. IOS is not affected.", "updateAuthor": { "name": "jbrackett", "key": "jbrackett", "displayName": "Josh", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2012-09-07T17:29:58.000+0000", "updated": "2012-09-07T17:29:58.000+0000" }, { "id": "224504", "author": { "name": "shossain", "key": "shossain", "displayName": "Shak Hossain", "active": false, "timeZone": "America/Los_Angeles" }, "body": "Escalating it for Homes.com. ", "updateAuthor": { "name": "shossain", "key": "shossain", "displayName": "Shak Hossain", "active": false, "timeZone": "America/Los_Angeles" }, "created": "2012-10-19T19:09:29.000+0000", "updated": "2012-10-19T19:09:29.000+0000" }, { "id": "224530", "author": { "name": "anagesh", "key": "anagesh", "displayName": "Anirudh Nagesh", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Tested it on Master build 3.1.0.v20121019134913 and 3.X CI build 3.0.0.v20121019103112 with Android 3.1, 4.0 and 4.1. Same delay ( ~9secs ) is observed.", "updateAuthor": { "name": "anagesh", "key": "anagesh", "displayName": "Anirudh Nagesh", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2012-10-19T21:34:25.000+0000", "updated": "2012-10-19T21:34:25.000+0000" }, { "id": "225457", "author": { "name": "krowley", "key": "krowley", "displayName": "Karl Rowley", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Pull request https://github.com/appcelerator/titanium_mobile/pull/3351", "updateAuthor": { "name": "krowley", "key": "krowley", "displayName": "Karl Rowley", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2012-10-29T23:30:53.000+0000", "updated": "2012-10-29T23:30:53.000+0000" }, { "id": "225475", "author": { "name": "krowley", "key": "krowley", "displayName": "Karl Rowley", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Notes on testing this fix for engineering and QE:\n\n(1) Ivan's example above consistently takes 8+ seconds to start on\n my Samsung Galaxy SII. After that the refresh of the picker is fairly \n quick (i.e. without restarting the app).\n\n So you'll need to make sure that the app is not running if you want \n to see the bug here.\n\n If app is already started, go to \"Settings\", then \"Applications\",\n select your test app and then click on \"Force Stop\", and then start\n the app.\n\n(2) With the change the app takes approx. 0.4 to 0.5 seconds to start,\n which is in line with the start time for the TableView example.", "updateAuthor": { "name": "krowley", "key": "krowley", "displayName": "Karl Rowley", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2012-10-30T01:37:44.000+0000", "updated": "2012-10-30T01:37:44.000+0000" }, { "id": "225577", "author": { "name": "krowley", "key": "krowley", "displayName": "Karl Rowley", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Re-opening pending pull request for 3_0_X branch", "updateAuthor": { "name": "krowley", "key": "krowley", "displayName": "Karl Rowley", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2012-10-30T21:22:23.000+0000", "updated": "2012-10-30T21:22:23.000+0000" }, { "id": "225587", "author": { "name": "krowley", "key": "krowley", "displayName": "Karl Rowley", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Pull request https://github.com/appcelerator/titanium_mobile/pull/3361 for 3_0_X branch", "updateAuthor": { "name": "krowley", "key": "krowley", "displayName": "Karl Rowley", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2012-10-30T22:00:10.000+0000", "updated": "2012-10-30T22:00:10.000+0000" }, { "id": "230083", "author": { "name": "nhuynh", "key": "nhuynh", "displayName": "Natalie Huynh", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Tested with 3.0.0.v20121204144658 on Droid 1 2.2.3", "updateAuthor": { "name": "nhuynh", "key": "nhuynh", "displayName": "Natalie Huynh", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2012-12-05T18:46:06.000+0000", "updated": "2012-12-05T18:46:06.000+0000" } ], "maxResults": 15, "total": 15, "startAt": 0 } } }