Performance Q&A guide

Next batch of questions (skipping things that someone else already gave a good answer to in the thread):

“If I have a bunch of image thumbnails on a page and the source is a full sized image does that mean the page has to wait for all of the full sized images to download?”

Generally we’re good about resizing things on the server. But you can check for yourself: if you look at the image url in the browser, you’ll see something like: “?w=380.94643874044306&h=243.1&fit=crop” at the end of the url if we’re resizing it on the backend. And you can copy / paste the url into a new tab and see how big it is.

“Is there any performance trade off between different ways of doing the same thing? For example, I can display an image in an image element, in the background of a group, or in an html element.”

Mostly not. See above answer about resizing – the biggest cost of displaying an image is downloading the full thing, so you can check the image url to see what size we are actually downloading it at.

“In order to increase my app speed, should I regularly clean my database to remove all items that have the validity flag set to “no” in order to speed up these searches ?
In a more general case, can we expect a bubble app to get slower and slower because the database is growing, even if we are not displaying more items (we are just keeping old data, but only display fresh one) ?
And when does this becomes critical (i.e., how fast is a search on server side before transmitting the data depending on the number of items in the database) ?”

Generally, having more stuff in the database that isn’t loaded in a search shouldn’t slow things down too much. We automatically build database indexes that let us quickly find things that match a search criteria. The very first time you do a particular kind of search, we don’t have an index yet, so that will be noticeably slower (perhaps very slow) on big databases, but we auto-detect that happening and build an index, so that in maybe 15 minutes to an hour, that search is fast. So, I wouldn’t worry too much about cleaning up old data. That said, if you know you never need a piece of data again, it doesn’t hurt to delete it.

“Thanks for the tips regarding data. What about the timing related to navigation from page to page?”

There are two things that control navigation speed:

-Page load time of the page you are navigating to. The biggest factor here is the amount of data the page relies on, which is why I opened this conversation with optimizing data use. It also matters how many elements are on the page: a page with only a few elements will load faster than a page with hundreds of elements.

-Whether there are any ongoing operations on the page you are navigating from. When you use a “change page” action, we don’t actually change the page until we are sure that it’s safe, so if there are other workflows running, we’ll wait til they are far enough along that we know it is okay to change. This just matters for the change page action, though… if you navigate via a link, the only thing that matters is the page you are going to.

"How does the number of

used plugins
unused plugins
affect performance?

Are some elements more intensive than others?"

An app with lots of pages with few elements on each one is going to be faster in general than an app with a few pages with lots of elements. When you navigate to a page, we have to load all the elements on the page, and all the custom definitions needed for custom elements on that page. But, we don’t need to load any other pages in the app, and we don’t need to load custom definitions that aren’t used on that page, so we don’t send that data.

For the most part, the number of elements has a bigger affect on speed than what type they are: ie, there’s no real difference between a group and a text in terms of page speed. The one major exception here is repeating groups: repeating groups basically multiply the load speed by the number of cells they display. If you have a repeating group inside a repeating group, and both have a lot of visible cells, that can get very slow.

Plugins sometimes affect page load speed even if you aren’t using them. We often have to include the javascript to run the plugin as part of the page’s javascript whether or not you actually need that plugin, so my recommendation is if you know you aren’t using a plugin, to uninstall it.

"Consider a repeating group with content type as Thing 1:
And a text box showing the following:
This Thing1’s Thing2’s Thing3’s Thing4’s Thing5’s… Thing(n)'s email

Now the database has to traverse n things to find email - what is the ideal way to call something nested so deep?"

Yeah, so as you correctly guess, that’s going to be slow… We have to load thing1, then load thing2, then load thing3. The best way is to just avoid that kind of chain. If you’re having a hard time figuring out how to design your app without doing it, you might want to start a seperate forum thread and solicit opinions.

"There’s a sequence or hierarchy in Bubble. Can you describe it, or at least a simplified version? What order does everything happen in? Which things can happen in parallel if they’re setup correctly?

I imagine it’s something like this
page > group > element > expression"

So, the first thing we do is we draw all the visible elements on the page, and then in parallel, start calculating the properties for each visible element (including fetching any data from the database). It takes much, much longer to fetch data than it does to render the element, so it doesn’t make too much of a difference if you put a something in a group, vs putting it directly on the page; they’ll both be rendered within the same couple miliseconds, and then they’ll send off any database requests they need to display their properties.

We don’t start rendering / fetching data for invisible elements until they actually get displayed. (With the exception that if you reference an invisible group’s data source, that forces us to kick it off). Generally this is a good trade-off, because the more data we fetch and elements we load on page load, the longer it takes for the page to load, so it’s better to take a little longer to display an element when you do make it visible than pay that cost upfront when the user can’t even see it. That said, in certain situations you might want to force data to load by having an element be transparent or covered up rather than actually invisible. (We do render covered-up elements because it’s too hard to tell whether or not the user can see them).

The other big thing that controls hierarchy in initial page rendering is when one element’s properties reference another element’s properties. This basically works like you would expect it to… if you’re displaying a search in a repeating group, and the search has a constraint that uses a group’s current item, obviously we can’t do the search until we’ve loaded the groups’ item.