{"action":"created","issue":{"url":"https://api.github.com/repos/meteor/meteor/issues/3976","labels_url":"https://api.github.com/repos/meteor/meteor/issues/3976/labels{/name}","comments_url":"https://api.github.com/repos/meteor/meteor/issues/3976/comments","events_url":"https://api.github.com/repos/meteor/meteor/issues/3976/events","html_url":"https://github.com/meteor/meteor/issues/3976","id":63178559,"number":3976,"title":"[Performance] Add .pause for Blaze reactive update while data is arriving?","user":{"login":"fungilation","id":3803466,"avatar_url":"https://avatars.githubusercontent.com/u/3803466?v=3","gravatar_id":"","url":"https://api.github.com/users/fungilation","html_url":"https://github.com/fungilation","followers_url":"https://api.github.com/users/fungilation/followers","following_url":"https://api.github.com/users/fungilation/following{/other_user}","gists_url":"https://api.github.com/users/fungilation/gists{/gist_id}","starred_url":"https://api.github.com/users/fungilation/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fungilation/subscriptions","organizations_url":"https://api.github.com/users/fungilation/orgs","repos_url":"https://api.github.com/users/fungilation/repos","events_url":"https://api.github.com/users/fungilation/events{/privacy}","received_events_url":"https://api.github.com/users/fungilation/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/meteor/meteor/labels/feature","name":"feature","color":"02d7e1"},{"url":"https://api.github.com/repos/meteor/meteor/labels/Project:Blaze","name":"Project:Blaze","color":"eb6420"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":11,"created_at":"2015-03-20T06:48:09Z","updated_at":"2015-10-15T03:18:10Z","closed_at":null,"body":"Continuing from https://forums.meteor.com/t/blaze-rendering-abnormally-slow-on-large-subsequent-dom-changes-iphone/1153\r\n\r\nConsider a typical infinite scroll app. In my case at http://clubch.at/, a chat app. It loads 100 messages on initial page load, with Messages subscription done in a Iron Router waitOn so it doesn't render template until data is done loading. More messages are loaded on demand, at increments of 50 at a time in my case. This is how I did it before, with a 2nd subscription to the same publication 'msgsByClub with Media, Votes', but with a reactive var as the sub limit instead of the a static 100 as limit in the sub in the waitOn:\r\n\r\n```coffeescript\r\nTracker.autorun -> if Router.current()\r\n  Template.instance().subscribe 'msgsByClub with Media, Votes', Router.current().params._clubName, Session.get('clubMsgsLimit ' + Router.current().params._clubName)\r\n```\r\n\r\nThis is the way most people would suggest online, by setting a reactive var as the subscription limit. The problem with this is performance, vastly exaggerated by slow performance on mobile browsers which my app is targeting. Blaze as I've observed would attempt to render while data is arriving on iOS, in a staggered fashion. Of the 50 increment messages incoming, 5 would get rendered, more data arrive after a second, 5 more render, etc. On my iPhone 6 (which is no slow device), it would take 20-30s to finish rendering the 50 additional messages, while the UI is highly unresponsive and CPU is constantly pegged at 100%. (this is a case for Meteor to add Web Workers support to better utilize multiple cpu cores? Side topic)\r\n\r\nThe performance problem here is that on mobile, rendering is too slow and it chokes while attempting to render as data arrives, when Blaze should not render updates while data is arriving and CPU is pegged. On desktop browsers (Chrome) this isn't an issue, 50 messages gets rendered almost instantly in less than a second.\r\n\r\nTo illustrate how this rendering while data is arriving completely kills performance on mobile safari: A initial loading of 200 messages, in a IR waitOn subscription, gets rendered in less than a second on the iPhone. As such, I've done a workaround (hack?) that is working well for my app running at http://clubch.at/ currently, by requesting the 50 messages increment in bulk via a Meteor method call and then injecting the data into minimongo all at once. The above client code becomes this:\r\n\r\n```coffeescript\r\nTracker.autorun -> if Router.current()\r\n  skip = Messages.find({ club_name: Router.current().params._clubName }).count()\r\n  limit = Session.get('clubMsgsLimit ' + Router.current().params._clubName) - skip\r\n  if limit > 0\r\n    Meteor.call 'MessagesPage', Router.current().params._clubName, skip, limit, (error, result) ->\r\n      if !error\r\n        result.forEach (msg) ->\r\n          return  if Messages._collection.find(msg._id).count() > 0\r\n          Messages._collection.insert msg    # I feel slightly dirty abusing minimongo here. I do clean up after myself with _collection.remove on route change later\r\n```\r\n\r\nAnd the server method:\r\n```coffeescript\r\nMeteor.methods          \r\n  MessagesPage: (clubName, skip, limit) ->\r\n    cursor = Messages.find\r\n      club_name: clubName\r\n    ,\r\n      skip: skip\r\n      limit: limit\r\n      sort: { createdAt: -1 }\r\n    return cursor.fetch()\r\n```\r\n\r\nThe result is the 50 new messages gets rendered by Blaze in less than a second! Instead of the 20s+ it took for it to completely render before when subscription limit was raised by a Session var and gets rendered chunk by chunk.\r\n\r\nI'm writing this here as more than just an account of my experience. Infinite scroll on mobile devices is a common enough pattern and use case nowadays, and I get the feeling that a performance bottleneck like this is overlooked as Meteor dev is still mostly done for desktop apps? If I'm doing something stupid here by hacking with minimongo like this, please let me know too as I haven't worked with Meteor for too long and not too familiar with Blaze's API and internals. If there's a method to pause reactive update of a select Template, so it can be resumed only when a subscription is Ready again after new data completes loading, there'd be no need then for my minimongo hack.\r\n\r\nMany pennies for your thoughts."},"comment":{"url":"https://api.github.com/repos/meteor/meteor/issues/comments/148270622","html_url":"https://github.com/meteor/meteor/issues/3976#issuecomment-148270622","issue_url":"https://api.github.com/repos/meteor/meteor/issues/3976","id":148270622,"user":{"login":"fungilation","id":3803466,"avatar_url":"https://avatars.githubusercontent.com/u/3803466?v=3","gravatar_id":"","url":"https://api.github.com/users/fungilation","html_url":"https://github.com/fungilation","followers_url":"https://api.github.com/users/fungilation/followers","following_url":"https://api.github.com/users/fungilation/following{/other_user}","gists_url":"https://api.github.com/users/fungilation/gists{/gist_id}","starred_url":"https://api.github.com/users/fungilation/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fungilation/subscriptions","organizations_url":"https://api.github.com/users/fungilation/orgs","repos_url":"https://api.github.com/users/fungilation/repos","events_url":"https://api.github.com/users/fungilation/events{/privacy}","received_events_url":"https://api.github.com/users/fungilation/received_events","type":"User","site_admin":false},"created_at":"2015-10-15T03:18:10Z","updated_at":"2015-10-15T03:18:10Z","body":"I guess that's a more general case/request of the problem I had."}}