For the past few months we have been building our Anvil web app using the personal plan. Most of our pages are some sorts of dashboards with graphs (Plotly) and tables. At first, our pages took a really long time to load, around 15 to 30 sec depending on which page. After some reading on the forums, we figured that we needed to do a single round-trip per page between the client and server.
After implementing the single round-trip, the loading times now vary between 5 to 15 seconds which is a big improvement but not perfect. The time it takes to fetch the data is relatively small compared to the time it takes to generate those tables/graphs.
After reading on the different plans, I saw that the Professional plan advertised a “medium” CPU/RAM machine, compared to the “light” machine for the Personal plan. Since we are working a lot with data frames and graphs, I was hoping that a better CPU/RAM combo would help us reduce the loading time, but after upgrading, nothing changed.
Am I missing something? What else could we do to improve those loading times?
Without looking at the application, you were most likely not hitting your CPU/RAM limitations in the personal plan.
Often the biggest time cost when making server calls in the free to professional plans is the building of the server environment. These plans do not have a persistent server, so every time you make a server call, you are re-building that server.
To get the persistent server benefits, you’ll have to be on the business plan.
Have you tried to compare the plot generation time on Anvil and to locally on your computer?
Very likely your computer is optimized for local performances, while Anvil server is optimized for network loads, so very unlikely you will get better CPU performance on the Anvil server than on your computer.
For example, if the Anvil server takes 5 seconds and your computer takes 3 seconds, I’m afraid there is little that can be done.
If your computer takes less than one second, then it may be worth digging a little deeper. For example how large is the serialized data that the server sends to the client?
If you are sending megabytes, then you may try sub-sampling or optimizing on that front.
Have you profiled which parts of the server call are eating up the time? Is it the import statement for pandas or plotly? Is it reading in the data from Data Tables or elsewhere? Or is it creating the graphs (if that is done server-side)?
Since then, I have been doing a little more dinging.
First of all, depending on which page I am serving, the server takes approximately 2-4 seconds before it is sent to the client. We are connected to a database on AWS but the data fetching is less than a second. For each of my page I am doing a single call to the server and I return one dictionary. This dictionary contains pandas dataframes and plotly figures that are done server side. My biggest call between the client/server seems to be around 1 megabyte in size.
My most problematic page can take about 17 seconds to finish rendering, the server side computation is about 4 seconds and the client rendering is less than a second. So that leaves me with around 13 seconds of idle time for the data to be transferred between the server and client.
Is my dictionary to big? Since I cannot use pandas or numpy on the client side it made sense to do it all on server side, but the data transfer seems to be the bottleneck.
I don’t know if there are interactive features that require the data to be processed on the client side, and I’ve never played with plotly or dataframes, so I may not be the right person to address this problem, but I would:
Do as much as possible on the server side and pass the final result to the client. If all you need is an image, then you can very likely generate a 30 kb image on the server in less time that it would take in the client, and transfer it in less time than it would take transferring a 1 mb dictionary
Shrink your data sample. Unless you have some interactive tool that allows to pan and zoom through your data, using 1 mb sounds like the resolution is too high. You should be able to aggregate or sub sample your data and create a much much smaller data set to get an identical result
I’m not entirely clear on what you mean by this, but I’m guessing that you’re comparing a client timestamp with a server-side timestamp to determine whether the latency is before or after the server runs. If so, I’d be careful with drawing such conclusions as they depend on synchronization of the client- and server-side clocks (on the precision of which I think physics puts some limits).
Optimization is an area with many moving parts. What you’ve got up until now has been general advice, because you’ve only provided general guidance on what you’re doing. If you were to provide a clone of an app that exhibited the slow server call that people could play with (create a minimal clone, not your large original app), you’d likely get more specific advice to your situation.