As of a few weeks ago, my production app started running much more slowly. It is now at the point of being barely usable by my customers.
All heavy lifting is completed via scheduled background tasks and those run fine. But the client side continues to be very slow for any kind of action:
Initializing form and getting current user info takes about 20 seconds
Reading one value from a cookie takes 13 seconds
Pulling a list of values from Data Tables and putting them into a dropdown takes 18 seconds
Changing a few display ‘cards’ to not visible takes 19 seconds
Pulling a stored figure from Data Tables and displaying it takes about 30 or more seconds, often causing client timeout errors
In case it is useful, here is the start of my MainForm. This shows code usually takes between 18 and 22 seconds to execute for users who are already logged in (log-in status is persisted for 1-year).
class MainForm(MainFormTemplate):
def __init__(self, **properties):
t_pre_init = datetime.now()
# Set Form properties and Data Bindings.
self.init_components(**properties)
anvil.users.login_with_form()
self.user_type = anvil.server.call('get_user_type')
t_post_user_type = datetime.now()
print(f"initialize + get user info took {(t_post_user_type - t_pre_init).seconds}")
Could I be doing something wrong? Is there any way to fix this?
Those timings seem incredibly slow.
I guess the question is - what does that server call do? I presume it’s that server call that is taking all those 20seconds
There are some posts about how to improve speed in the forum.
Typically if I have something on the client that’s taking more than 1second to complete (usually because of retrieving and manipulating data table stuff) I’ll work out ways to load the minimum necessary and turn the rest into a background task.
Have you tried adding a print('something') after each line of code? Keep in mind that prints on the client side are fast, while each print on the server side requires a round trip, but only when you run the app in the ide.
Have you tried to remove all the data bindings? Sometimes they trigger round trips, and sometimes they call slow functions. I sometimes put a print('function name') as the first line of each server function, so i can look at the log and detect unexpected calls.
Have you looked at the app log and noticed anything unexpected?
Thanks, @Tony.Nguyen. I am on the individual plan.
I’ve found significant differences in execution time based on time of day so I wonder if it has to do with number of users, or perhaps my app is being run on a shared resources and it has to do with other apps reducing their load? Usage of my app doesn’t change that much during the day since I am running kiosks that update their data 24/7.
I looked at the business plan but it seems that you have to pay $300/month just to have the opportunity to pay $100/month per extra compute unit.
I forgot to include the server-side code but it is something very simple that shouldn’t take long. Even pure client-side code seems bogged down.
I’m doing most of my heavy lifting via background tasks but am making a lot of calls to server functions from the client, to retrieve data stored by the background tasks, etc. Thanks for the link on how to optimize. I think the advice to reduce number of server calls might help me out.
Interesting info about the server-side print statements requiring round trips, but only when run in the IDE. I had no idea about that, and it certainly could be affecting my performance calcs.
After I ready your reply I thought about it and I realized that what I wrote earlier doesn’t make any sense. Both server and client side prints access the app log, so:
when running on the IDE they both require a round trip, the client for logging, the server for displaying
when running the production environment, the client requires the round trip to access the log, while the server doesn’t require the round trip because it doesn’t need to print on the console
So… I apologize for giving the wrong information, and kudos to the Anvil team: I made a quick test, and the prints are very fast both on the IDE and on production. Perhaps the round trips required for logging are not synchronous and each print takes at most one thousand of a second.
Obviously, printing the result of a function that triggers round trips or is otherwise slow, would not help, but, yeah, obviously.
I still stand (so far) by the other consideration on my previous post about the round trip required by the data binding.
Are you still struggling with this? This server call
has got to be doing it. We run into this kind of thing a lot with Anvil.
If you haven’t already solved it, I would look closely at your server imports, or post your code (or a clonable link) for more info.
Note that Anvil may load all your server code on any call, so a server module that’s slow to initialize (slow imports or slow code in the global scope) may slow down other calls.
Try removing all server code, and installing a simple module that does nothing. Call that to get a baseline, including the Round Trip Time for your location. I’ll bet if you remove all server code, the time will come down to 1-2 seconds, tops. Then you can put things back half at a time to find out where the real time sink is.
Another option: look at the server-side changes that were made just before the slowdown occurred.
In my case, it was a set of plotting routines. I had added 3 imports. By moving those imports into the functions that needed them – by importing them only when actually needed – the other server calls went noticeably faster.
In other cases, it might be a new set of database operations. In those cases, caching results in anvil.server.session might speed things up a bit.