Performance Q&A guide

Hi @blueback09 , yes, that will expression will work: it will retrieve at most one result. However, this will also work:

search: count > 0

Bubble is smart enough to recognize that pattern and load at most 1 item from the search.

In general, I would recommend expressing things as simply as possible. The most simple way of doing things isn’t always the fastest, but it often is, and we are constantly working to write database optimizations that take common patterns and rewrite them behind the scenes to be fast. The more complicated your expression is, the more likely our query optimizer won’t know what to do with it, and will just run it in a naive fashion instead of doing something intelligent.

4 Likes

Okay, thanks. So, rephrasing it to confirm understanding: if I have a condition like “greater than 0” on the count of a search, Bubble will automatically optimize it to stop searching after it’s flipped the condition from “no” to “yes”?

Does the same thing apply if I’ve got one element that has “search:count” in it and a different element has a condition “first element’s value > 0”?

I’ve been breaking up the logic into more and more discrete elements as I try to push Bubble to do things outside of its comfort zone. Sometimes I’ve got chains of logic almost a dozen elements long, each one handling a different part of the logic tree. Does that inherently confuse Bubble’s optimization, or does it all kind of get flattened so it can still be optimized?

Yes, more or less. Bubble might also choose to just fetch the total count without fetching any of the individual items, depending.

Yes, same as above (in this case it will likely fetch the total count).

It depends. Also, we’re always changing things. Rather than trying to memorize a set of (changing) rules, my advice is to test empirically in situations where performance is critical. Create a test page, with nothing on it except for the search(es) you want to investigate. Then use a tool such as Chrome’s developer tools (Инструменты разработчика Chrome  |  DevTools  |  Chrome for Developers) to look at the requests we send to the server. Requests that fetch data are send to the /elasticsearch/get, /elasticsearch/mget/, /elasticsearch/search, and /elasticsearch/msearch (before anyone asks, no, we don’t use elasticsearch… we used to, and the endpoint names are a legacy holdover from that). By looking at the response the server sends (and the size of the response), you can see how much data it takes Bubble to load a given search.

5 Likes

How do the privacy roles impact performance? For example, if the amount of records are reduced due to privacy roles, will the search performance improve?

2 Likes

Hope @josh is still around to answer performance questions :slight_smile:

Your answer to the same search:

Made me wonder follow-up questions:

  • Say you need current user’s thing’s thing’s {field A/B/C…} – and you need them in various places (elements, workflows, another search that relies on that dynamic data) … is it still okay to do search for a thing in each place? If so, how does Bubble smartly know the data? Is there some sort of cache system so even after the search is over on page load, that same searched data can be used on later workflows?

  • Would there be a performance payload/difference between two methods? 1) Do a search for in every place it needs, 2) Do a search for in one group or repeating group and other places reference that one source of truth?

I’d assume that: since the search requires two steps into the thing (user’s thing’s thing…), it would be better to have one group that holds that thing (current user’s things’ thing) and other elements and events/actions reference that group. That way I feel like Bubble doesn’t have to go in two steps to find that data every time.

4 Likes

Just a follow up, is search for still the most fast way to reference things. Along with that, does it matter which order the contraints are in.
Say I have a spoons (1000 total spoons) (red, Blue, green) in a drawer (50 total drawers) (kitchen drawer, buttler drawer) in a house (10 total houses) (my house, your house) and I want to search for a blue spoon in the buttler pantry of your house would the search constraints work better like

spoon = blue
drawer = buttler
house = your house

or

house = your house
drawer = butler
spoon = blue

3 Likes

Can someone shed some light on this chart?

A user started an api workflow on a list of 300 items (creating a new thing), which resulted in the server maxing out. We are on PRO plan and have 2 additional server units.

In the middle of the process I boosted with 5 more units, so totaling 7 additional units. This is the resulting chart:

Even though the app still hits maximum capacity, the avg CPU usage for the capacity now falls to around 100%. or maybe it would anyway and is now just stabilizing.

Looking at this chart, would this situation require at least another 5 units to get the avg CPU usage to around 50%? (which is still a lot imo).

Honestly, I feel that these additional server units do not add a lot of capacity if this chart is correct :frowning:

2 Likes

It’s an interesting point here. Following along to learn more about this, hopefully we get some insights!

1 Like

Would the extra units just increase the speed of which the workflow takes? I would have thought that unless the workflow is somehow limited that it would still use all the capacity available but the increase recourses would make that max out time less than if you did not have the extra capacity.
It would be interesting to know exactly how much a unit adds to ones application

Would love to have a chart, something like the picture below, that gives a visual picture of what causes performance issues

I like “VISUALS”, thats why i program on Bubble…

1 Like

Amazon has a E2 Unlimited service, it mean, the server has all the CPU power it needed for peek time. Maybe it’s coming to Bubble?

Must Read, this useful post needs to be linked to this thread.

2 Likes

There is!! Have a look in logs down the bottom of the page, second item from the bottom.

There’s a pie chart, click on it and it breaks it down

A simple question, yet intrigued to find a better answer. I want to increment the id field (of type number) +1 everytime a new thing is added. As I understand a way to do it is to search for the thing & apply : max on the id field. Even with a database table of no more than 5-10 rows, this is taking way too long. 2 things I would like to know:

  1. Is there a better way to fetch the max id number than what I wrote above?
  2. Since we are fetching the :max id & applying a +1 on it, what happens if consecutive users tap the same button at the same time. Is there a chance that the table may have more than 1 thing with the same id?

Will appreciate a quick response. @josh anybody else?

Thanks,
Shivam

Unfortunately, the answer to #2 is Yes, there is a chance they will get the same id. I so very much wish we had unique field constraints at the database level to protect against this, but today we don’t. The only truly unique id’s you can rely upon are the system fields bubble provides.

Thanks @mebeingken for a quick reply. May I know if there is a tried & tested way to create unique ids (say 6 digits long) from the veeeeeeery long unique ids that bubble generate?

I am kind of intrigued since unique ids are a part of most scenarios of maintaining DB tables. What are other folks doing about it? Haven’t anyone discovered a “workaround” to create unique ids by now?

Many Calls to Relatively Static Database Information

Dear Experienced Bubble Users and @josh,

My app has lots of data scattered around different Things which is very static, yet used all over the place. Examples are “My Business Name”, “My Accounting Currency”, “My Emails From Address” etc etc. These things are stored outside of the User record since my system allows an organisation to subscribe to my app and then create multiple users of their own.

I am assuming there has to be a full database call each time I use one of these values as Bubble doesn’t know if they were changed from one moment to the next.

Is this true?
Or is there some mechanism where Bubble keeps track of whether a value is relatively static and can access that value without an expensive database call?
If I am accessing such data from the User thing, does the answer change?

Assuming this is true, I’ve realised I can probably get quite a performance increase by reading these values just once when the user logs in and storing them in a “Static Info” state which I then use throughout the app.

Would this seem like a good idea?

I doubt that what you think of as “many” is actually “many”. Are you iterating over things a lot (this seems unlikely as Bubble more or less prohibits that)?

I could see something like “Accounting Currency” being referenced a lot in, for example, a repeating group. Do such repeating groups seem slow to load or display to you? If so, you could on page load set the value of a custom state to that value and then reference that custom state rather than (I’m just guessing here) something like Current User’s Company’s Accounting Currency.

Believe me @keith, when I say many, I mean many. It would take a while to explain my app, but as explained, it will have many “subscriber” users who themselves will have multiple users, and that is where some of the complexity comes in as every thing I search or view has to reference the subscriber user value.

Yes, I am just starting to implement a custom state system as you describe, but it is complex as there are my design has over 40 reusable elements it has to be passed into, and I’ll have to change a gazillion searches and views I have already written to use the new state, and I want to be sure I need to do this before I embark on the task.

The app seems okay now, but I know that as I get hundreds of users, each database call will cost me money in terms of how much I pay for capacity boost per user subscription I bring in.

This is ultimately a financial optimisation for my business! :slight_smile: