My app is too slow

What I’m trying to do:
I’m trying to run an app that does server calls from 5 different tablets at irregular intervals. In total, I’m doing around 20 calls per minute. The calls retrieve and insert info to database, which contains only a few hundreds of rows and a dozen columns.

What I’ve tried and what’s not working:
The app significantly slows down when doing this. I did a comparison with the debug env (which was not receiving the calls from the tablets) and doing a single call was 5x faster. We then switched to business plan, hoping it would fix this but it didn’t. I believe any server should be able to handle 5 simultaneous calls, isn’t it? Is it possible to get personalised attention here? I’d rather not expose all my code in the forum.

Code Sample:

# this is a formatted code snippet.
# paste your code between ``` 

Clone link:
I’d prefer to keep my app private.

You can get personalized attention from Anvil support by purchasing a support plan. Otherwise, you can get help on the forum, but obviously we’d need to be able to see more of what you’re actually doing. Often a full clone isn’t needed, just snippets of what you think the code that’s slowing things down is (both client and server).

There are so many reasons that an app might be slow that it’s impossible to give anything but general advice without seeing some concrete details.

There’s plenty of that general advice floating around on the forums if you search for it.

Hey, thanks for the quick answer. I see there’s an email for support, I’ll try to reach them there.

Best,
m

A big part of handling performance in Anvil is reducing server calls and caching data. There are a number of threads about this.

Even if you can’t reduce the amount of server calls, there are a bunch of things you can try to make your server calls more efficient. Also many threads about this in the forum. A few highlights

  • Using accelerated tables with q.only_cols and q.fetch_only
  • Moving imports inside functions if you don’t have persistent server, or using persistent server
  • Using background tasks if you are just updating the db without needing something back

Keep in mind that the Business plan still uses shared hosting and is not a dedicated server. Extra server resources is an extra add-on.

Hey!

I’m already using accelerated tables and I already have a persistent server, I’m also doing minimum server calls. Background tasks could be an option but I still believe it is a server related issue that I should explore first. My app runs fine on my laptop; doing the exact same calls from my browser (using multiple tabs) is not super fast but manageable. The problem comes when I use the tablets. I thought network saturation could somehow be the problem but everything else is running smoothly (youtube, etc). Then I thought the tablets might be the problem but the app also struggles on my computer. Did a test using the debug environment and performance was ok, the problem was in my production env, which was handling 5 tablets calls.

I have used anvil apps on tablets for a similar use case before, using background tasks for most server calls and using the no loading indicator context manager are definitely very helpful.
Depending on the cpu / rendering power of the tablets you may also try downloading the web app as a PWA directly to the devices, this helped me tremendously with user experience.

Hi @bufirolas,

20 requests a minute is about one call every 3 seconds. This shouldn’t be unreasonable, especially with Persistent Server enabled. As people have said earlier, a deep dive into your code from our team is a support-plan-only thing, but here are some general things to think about:

  • Is Persistent Server really switched on? Including in the version you’ve deployed, not just the debug version? You can triple check this by printing a message in the main body of a server module - with Persistent Server, you should not be seeing that message every time as your code is loaded once and then handles many requests.

  • How long does your server call take in an unloaded environment? If its ten seconds of CPU-bound work, then a new request every 3 seconds is filling the bucket faster than it’s emptying. (You can get more CPU power with the Extra Server Resources add-on, but unless you’re doing a lot of crunching that wouldn’t be my first port of call.)

  • There should be no difference between the same calls from a browser or a tablet or an Uplink. For testing purposes, you might like to try creating synthetic load by writing an Uplink script that calls the appropriate server functions at the appropriate rate (use multithreading or invoke your script multiple times in parallel if you want to simulate multiple simultaneous requests).

  • What are you actually doing in those server calls? If you can’t share your full code, a cut down example that replicates the problem would be ideal, but failing that a textual description of the workload might give the folks on this forum some hints!

1 Like

With systems as deeply layered, cached, and optimized as Anvil, surprises are almost inevitable. So, as a general recommendation…

  • When in doubt, measure the start and end times of each distinct call, and intermediate steps, to pinpoint where the time is going.
  • When not in doubt, measure anyway. You’re almost sure to be surprised.
  • You may have concurrent calls going on, so each incoming call will probably need its own unique id, to include with each timestamp.
    • Don’t set this as a global variable! Otherwise a new call can overwrite another call’s id, before the first call finishes! This would mess up the labelling.
  • Only when you’ve measured the time can you reliably tell where to spend your optimization efforts.
  • After optimizing, measure again. You may still be surprised where the time is going.

Thanks for your insights.

  • Indeed, it seems that persistent server is NOT turned on, as I’m seeing the message repeated on every call. How can I turn it on?

  • Every call takes around 2-3 seconds in a normal, unloaded context. This is ok. The problem is when these calls take 10-20 seconds each. Tbh this is a fairly simple app, without any complex crunching involved. Also, my tables are fairly small yet.

  • About the synthetic load, I did something similar. Using my browser with multiple tabs, doing multiple calls simultaneously. Using time and print statements for measuring, there was any noticeable difference between doing 1 call per minute and 30 calls per minute. I must mention that this was tested on a different network. The “production” network is geographycally apart and I’m just having trouble on this here, not at my place. However, as mentioned before, the “production” network seemed to be fine, running Youtube and more without trouble. Any ideas here?

  • No big secrets. The app is basically a scoring app, where each tablet runs a different game score script that updates the server periodically. We’re talking about table tennis games here, so points are being made fairly often, however I did optimise the load so the score is only updated every X seconds and only if the score was modified. Each game should do a call every 30 seconds or more in average, aprox. We’re mostly talking about row updates and only a few calls from a monitoring dashboard.

Hope this helps!

Go to your App settings (the gear icon on the left), then Python Versions, and look toward the bottom:
image

4 Likes

this is it! Thanks!!

How much did enabling this improve speed?

It is a considerable difference!