Performance Q&A guide

Couple quick updates:

-Autobinding: haven’t gotten a chance to debug this further yet, sorry. Will update when I do.

-@blueback09 There’s two solutions here. One is to manually create a field on the Parent thing with the contents of something, like you suggest. If the Something field is the main thing you’re using to retrieve Parents by, that’s probably the fastest. The other thing you can do is if you can narrow the set of Parents you might want to search down using fields stored on the Parent, you can then use an advanced filter to filter out Parents whose something doesn’t contain what you are looking for. This is only going to be efficient if you can shrink the number of Parents in the initial search to a number that’s not too big, since we can’t apply advanced filters without loading all of the data.

@johncottongim – it’s generally better to update a bunch of fields at once rather than lots of small updates in terms of write speed and on-screen performance. Re: page size, unless you have hundreds of workflows, visual elements generally contribute much more to total page size than actions / events, so I wouldn’t worry about optimizing that.

@florent.bocquelet – we’re not doing anything smart right now re: optimizing booleans… we’ll still do the search. That may change in the future, though, since that’s a common optimization in programming. Yes, putting it in a seperate conditional will get around this limitation for now.

@nathan.d.stevens – The main factor in long scripting times is total number of elements (and how complex / how many properties) elements have. Repeating groups are often a culprit in pushing up the total number of elements: a repeating group with 10 cells each containing two elements is faster than having 20 seperate elements, but it’s still much slower than 3 elements. You can control the timing via keeping things invisible; we generally don’t render elements until they become visible, so if you have most of your page in an invisible group, then show it a half-second after page load, you shouldn’t have the 5000 ms cost until that half-second delay, and in the interim you can display a lightweight message. (That said, the logic about when elements get rendered is a little complicated, so YMMV; test this empirically on your own app…)

3 Likes

Hey @bubble5, @kahan.jonathan, @gurun, @florent.bocquelet – we just deployed some fixes that should make auto-binding more reliable. Let me know if you see a difference or if it still feels buggy.

2 Likes

@josh obviously it is not ideal to store a list of things on a piece of data, if the list can be in the thousands and can be avoided. But occasionally it seems necessary, like in the case of a Twitter clone. To track Likes on a tweet, I would either have to assign a list of Users to a Tweet OR to assign a List of Tweets (liked) to a User. Either way the lists could potentially be in the thousands.

So in this type of scenario, to make sure a User and a Tweet load optimally, is it better to save a List of Texts (unique IDs), than to save a List of the Data Type?

Or is there a better way to structure this data to store a large list to a piece of Data?
Such as creating a Like as a data type and assigning the User and the Tweet to it?

2 Likes

What’s the difference between 1) having an invisible element whose data source is referenced (thus start loading data) and 2) having a transparent / covered-up element? As far as I understand, both invisible and transparent elements would fetch data – then what are certain situations transparent elements are more suitable than invisible elements?

I have the following structure:

  • A repeating group (6 cells with infinite scroll)
    • A repeating group (fixed number 7 cells – 2 elements in each cell)
    • A repeating group (fixed number 10 cells – 2 elements in each cell)
    • A repeating group (fixed number 3 cells – 2 elements in each cell)

All nested repeating groups don’t do a search – they simply reference the parent repeating group’s search. Is this equivalent to:

  • A repeating group
    • 7 groups (2 elements in each group)
    • 10 groups (2 elements in each group)
    • 3 groups (2 elements in each group)

Would either one be any faster?
When you said “lots of visible cells can get very slow”, how many cells?

  1. Can you please elaborate on how indexes are designed? Are these focused on the unique PK fields or more specific to how I’m doing search for queries in my app?

  2. Is the purpose of field type “list of things” performance? How does this compare to adding the grandparent id to the parent table thereby circumventing a nested search?

Which method is better: Speed is an issue vs. Speed is an issue?

1 Like

Few more questions:

  1. Is there any performance difference between putting a condition on a workflow v. putting that same condition on a single action within a workflow:slight_smile:

  2. I know, as you’ve previously said, that there is a purposeful delay put on a “Scheduling a Workflow on a List”.
    Today this appears to be 5sec or longer. We’re using “Schedule a Workflow on a List” that hits another API endpoint to add multi-row API responses on row at a time into our database. My question is: If we limited the number of fields or the quantity of the data that is written to the database, would this improve performance? All the fields are <300bits in size.

When en element has to refer to a parent groups thing, does this affect performance? Some of my pages have groups up to five levels deep referencing a groups Thing.

This cannot be changed to the page’s Thing because the user clicks a Thing from a list and a new group is shown, not a new page (where I can transfer the thing to)

So where is the dropoff for the number of items? And what is faster:

Do a search for Invoices with Company being X, then having a couple of other constraints (filter, sort)

Refer to Company’s Invoices with a :filtered action to add the constraints?

Yes, currently this is the most scalable way to build this. We eventually plan to do this automatically behind the scenes (ie, have it feel like a list, but actually be a separate table in the database) but that might not be for a while, so your suggesting of having a Like datatype is a good work around.

Invisible elements only fetch data if you force them to by referencing their data source. Transparent elements will fetch data regardless, so if you don’t want to reference their datasource from a visible element, but want them to show instantly with their data fully loaded, that’s why you might want to do that. That said, don’t go crazy with that technique – otherwise you’ll be paying the cost of loading all the page’s data upfront instead of just when you need it.

This is the kind of thing that’s easiest to just test empirically – depends on a lot of factors. I’m trying to give general guidance but at the end of the day, a lot of things are trade-offs and you should see what works on your app.

Specific to searches – we monitor for searches that take a long time to return their first result (generally indicative of a situation where indexing can help), and build indexes to support that particular search.

Primary purpose is to make it easy for users to create a list – it’s cumbersome to have to work backwards via a Search. See above re: future plans to make this more scalable via switching to having a relationship table vs storing it as an array on the record itself. Not sure I follow how using a list is an alternative to the technique of storing a grandparent reference directly on the object. (There shouldn’t be a performance difference between storing the unique id in a text field and just storing a reference to the object, since behind-the-scenes, a direct reference is just us storing the id as text)

Well, skipping an entire workflow is faster than skipping just one action…

The main variable is number of items in the list, not the size of each item

Referencing a parent group’s thing should be a pretty fast operation[quote=“vincent56, post:51, topic:12140”]
So where is the dropoff for the number of items? And what is faster:

Do a search for Invoices with Company being X, then having a couple of other constraints (filter, sort)

Refer to Company’s Invoices with a :filtered action to add the constraints?
[/quote]

Re: drop-off, test empirically in the context of your app: varies based on item size, what queries you do, etc.

If you can put a filter in the original search, that’s almost always at least as fast or faster. We’re working on some improvements to be smarter about :filtered messages, but those improvements basically boil down to executing the filter as part of the original search if we can, so best case it will become just as fast.

4 Likes

@josh - regarding your comments quoted below, how does this principle apply to popups? Let’s say I have a reusable element that is a navigation bar loaded on a page. This reusable navigation bar includes 3 popups (i.e. Edit Profile, Update Profile, Update Profile Photo, etc.). Are these popups loaded each time a Page containing the reusable navigation bar loaded, or are the popups loaded only when activated (i.e. when the Workflow is activated which shows a particular popup)?

Thanks!

1 Like

Hello Bubble Community,

this is a great topic.

We have been using bubble for quite some time and really like it, but unfortunately speed is a big issue for us.

We have been trying to solve this by taking some steps on our content side, e.g. compressing pictures and we also switched to a dedicated server plan.

However, we are still not happy with the speed of our site www.pflegetiger.de

We would be more than happy if some people have recommendations for us.

The site was fairly fast, as I poked around it. Which specific pages or elements do you think are slow?

Hi Robert,

especially our index page www.pflegetiger.de and jobs page www.pflegetiger.de/jobs are important for us.

Different speed test show load times between 12 and 14 seconds.

This is an issue for Adwords (lower quality score, high bounce rate from clicks to visitors) and for the page experience, which also leads to a high bounce rate.

both pages loaded in under 3 seconds for me.

I’m getting similar results to you. While 3 seconds is still a long time, it’s nowhere near the 12 and 14 mentioned by @Pflegetiger. I’m in Virginia near the AWS east data center, so I wonder if this makes things faster for me?

Took 4 seconds for me, so unless stuff needs to load in the back that I cant see it’s about the same for me. I’m in the Netherlands.

Is there a tool that can pinpoint the elements or actions that are the bottlenecks?

I’m consistently getting under 4 seconds, and sometimes under 3.

You could compress your images. That background image is 1.2MB…can get that down to 350k or less with minimal loss.

2 Likes

Thanks for checking it out. On my device to load time varies between 4-9 seconds depending on the internet speed (glas fiber at work and still quite fast internet at home)

This is what different tests show us:
https://www.webpagetest.org/result/170703_DE_QRT/
https://gtmetrix.com/reports/www.pflegetiger.de/EyIwdtCg
https://developers.google.com/speed/pagespeed/insights/?hl=de&url=www.pflegetiger.de&tab=mobile

Google Analytics points out that we have a latency problem, i.e. we are receiving more clicks on campaigns than we are receiving visitors.

Besides the other tests, the Google results matter a lot for us, as page load time influences the quality score of the page.