New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Blaze speed and memory issues #3596
Comments
I hope @chandika is also having this issue. |
Yes we do! The GC process when destroying and creating templates takes a huge amount of time and makes apps largely unusable when there is a substantial amount of data. |
I'm afraid my CEO will be like that if he finds out ;) I love meteor, but this might be a show stopper... We need to handle a lot of data and are also seeing performance issues. |
Another data point – load time for the same page in my app: |
I'm looking into this now. Looks like 70% of the time is spent diffing the array. This definitely can be optimized. |
|
This is one of a longer sequence of changes we can make to make the diffing algorithm in Blaze be linear as opposed to quadratic which it is at the momeny, in general. This change specifically makes it so that the very common case of an {{#each}} over an array that switches from empty to a long array much faster, since the adds in those case are always at the end of the array. This means there's no bookkeeping necessary to update indexes. This changes reduces the rendering time from the example posted on #3596 from 5000ms to 1729ms.
@lorensr moreover, what for /you/ would be acceptable page load times for the app that you've linked to, and what numbers do you get now? (I'd like us to have a target for rendering time) |
Thanks so much for working on this! I've deployed an instance of my app to http://speed.meteor.com/signin and uploaded the same DB as below tests w/ 50 items. Login email is The goal for moving between pages in-app is to match native apps, so without any noticeable delay (scientifically 100ms). I'm planning on trying to get this by never removing pages from the DOM, just hiding/showing them when I move between pages. So the remaining timing problem is initial load, where the goal is also matching native. The slowest mainstream apps I can find take 4s (and since Cordova js+render speed seems to be ~6x slower than desktop, that gives a 700ms target for desktop load time). I can cut mine down a lot by initially only loading the 5 out of 50 items that the user can see on the first page. The problem that is harder to deal with is memory. If I load more feed items when I scroll down, to prevent the app from crashing I have to figure out whether I have to pause at some point to let garbage collection go and/or remove from the DOM the items at the top of the list.
|
Potential identical (or related) issues were mentioned in this thread: https://groups.google.com/forum/#!topic/meteor-core/Reb8WgxGURw |
Interestingly, when I record changing the limit of the list query, eg from 1 to 2, or from 20 to 21, and it only needs to render a single additional item, it takes longer if there are more items already in the list. Going from a list of 1 to a list of 2 takes 100ms scripting and 6ms painting/rendering, but: 20 to 21: For reference, it takes 2.54s to go from 1 to 71. Here is the 1 to 2: and exported CPU profile: https://dl.dropboxusercontent.com/u/27134267/single-list-item.cpuprofile 70 to 71:
|
I now really wish I kept reproducible copies of my code but let me share an experience if it helps. I needed to build a custom reservation calendar that showed 30 days and 12 custom time slots per day. Each slot would have a combination of states (occupied, has-discount-rates, currently-selected, occupied-by-current-user, closed-for-maintenance, prime-time). I also needed the past slots to be marked as "past" and shown grayed out as time passed. The customer also wanted the days to slide (shift by one day) exactly 1.5 hours after midnight. In their business terms, it was still the same day until 01:30am. Oh and these all had to happen preciesly at the server time within 1minute resolution. Anyhow, my first stab was to create a monolithic array. It chewed up memory but was still very responsive after the initial load which took around 10 seconds. But when I loaded up the app on an iphone (ios safari), the app just froze. iOS chrome was a little better, it at least managed to get up an running wihin the first minute. Then I decided to divide up everything into sub templates. A calendar template that called up "day" templates which called up "slot" templates. Now it is quite responsive on both desktop and mobile. Initial load is less than a few seconds. All I chaned was how I assembled the final html. Instead of doing it within one function that generates an array based structure, I divided it up into substructures managed by template helpers. I hope this helps. |
any updates on this? I'm rendering tables with ~300 rows, it takes about 3sec. (Not a show stopper, but noticeable) |
Hi, I was asked to post my issue (https://forums.meteor.com/t/list-of-results-with-a-template-per-list-item-very-slow-on-mobile/4683/2) here in this forum. I have a listing of items (coming from mongo) with an infinite scroll. Each list item has a tap event which opens a slide down below the list item with more information. I really liked the construct of calling a list item template in the list iterator, like this (JADE format) div.list This creates a template object for each list item with the benefit that the tap event within the list item has access to the THIS scope (which is the whole mongo document of the current iteration). There is only one problem, when I start scrolling on an ipad and have for example 50 list results, having so many list item template instances is really slowing down the mobile browser. When I tap on a list item it sometimes takes 2-3 seconds for any response on the tap event. All very laggy. I was a bit worried, cause mobile has to work in my solution. So I gave the issue some thought and figured there are currently a lot of models created with observers and so. So I ditched the listitem template and just added the markup directly in the EACH block. Now speeds are blazing on mobile, even with 300 results!
But I lost the elegant THIS scope benefit and now have to add data in my markup for the events to pickup. Is there anyway to use the list item template without having the performance issue, or is that just an inevitably? |EDIT| I noticed not using the list item template, still gives me the benefit of the this scope per list item. So it is not necessary to add templates per listitem. |
Additionally, I'm noticing that Blaze uses a setTimeout to render after the DOMContentLoaded event. Is that expected? |
The forum thread linked in #4674 has some benchmarks that are relevant even when the client has all the data. |
We're moving Blaze issues to it's own repo. If you have a reproduction repo that demonstrates a particular render speed issue, please open a new issue there: https://github.com/meteor/blaze This FR may help render perf: Also check out the Guide on view layer render performance: |
(I showed this to @avital at the Devshop and he said I should submit this.)
Blaze is not blazing fast☺️ Blaze takes ~3.5s to render a document with 30k dom nodes and ~350ms to switch to a template with 100 nodes. I think both take too long (even just 350ms is a noticeable delay for the user).
Reproduction:
http://slow-render-demo.meteor.com/
https://github.com/lorensr/slow-render-demo
Rendering the large template:
Small template:
These next shots are from a separate run, so numbers are a little different from first two pics. Recording manually while switching between the two templates twice:
The first large template takes 2.38s scripting (orange)
and 1s rendering (purple)
Compare to jQuery version (node count ~25k):
http://jsfiddle.net/2who62h4/2/
which spends 626ms scripting
and 38ms rendering
The heap size goes up linearly with the amount of time Blaze spends scripting. While in the simple reproduction above, the heap only gets up to 48MB, a real app has many subtemplates and more complicated data. In my app, a list of just 150 divs (each div more complex than just a number) is 120k nodes, 245MB heap, 10s scripting and 300ms rendering. It consistently crashes iOS Chrome on load. (I assume the OS is killing Chrome due to hitting a heap size limit. It takes half as long and does not crash Chrome when there are 75 things in the list.) Imagine a Twitter app in which you could only read 75 tweets at a time, and then you had to wait while it removed those 75 you read from the screen, garbage collected, and loaded the next 75. My CEO was like, "Well, guess it's time for you to give up on that Meteor thing and rewrite it in native code like that big design firm told us to do." 😭😝
My app:
The text was updated successfully, but these errors were encountered: