Hey guys,
I have a for loop that assigns the value of a key in a dictionary to a string returned by a function, and overall, and that function is a very slow process, so it takes around 30 seconds go through each loop. The entire loop takes 10 minutes (20 iterations), and I’d like to speed it up.
I can’t do anything about speeding up the function because it calls an API and that takes a very long time, but I can do something speeding up the loop.
On my computer, I would use the multiprocessing module to do a couple iterations together but I’m unable to do that in Anvil server code, it returns some errors.
Is there anyway I can speed up my for-loop?
Thanks in advance for answering!
You can run those lengthy calls in individual background tasks.
For each row kick off a background task and put the task object in a list. Then loop through the task objects and collect their return values when complete. You can also save information to the task state object which you can display on the user facing site to give a sense of loading progress.
I can’t actually do that, because the function that runs all of it is a separate function that may or may not run in conjunction with 10-15 other background tasks, and I don’t want to launch a lot of background processes in only one environment (I’m absolutely afraid that it may overwhelm the server when running so many background tasks in all the environments, combined)
Your account, unless on a dedicated server, has quotas on resource usage, so the server is safe.
But you are right, the server will not go down, but your app may be killed if your tasks use to much memory for example.
If launching too many background tasks would be too heavy for the server/quotas, launching processes instead of background tasks will be pretty much the same. The processes will use the resources that the background tasks doesn’t.
How do you launch processes?
I tried searching on the docs for the keyword “processes” but it returns to me background tasks only.
You can’t. There are background tasks for that.
Ok, if there’s nothing I can do, there’s nothing I can do.
If I understand correctly, a (running) Background Task is a process. It’s just running your app’s server-side Python code in its own Python interpreter instance, with the benefit of Anvil’s runtime support (including logging).
1 Like
Why do you say there is nothing you can do?
You can use background tasks.
Offhand, from what I’ve read, on a normal PC, this part sounds like a job for async
(because it’s I/O bound), not threading or multiprocessing. Ideally, one background task could handle it all. As such, it sounds like it ought to be much more server-friendly than spinning up a much larger number of background tasks, one per API call.
Whether that can work (safely) on an Anvil Server, I don’t know. I recall that there are several Forum conversations exploring that angle.
Caveat: I have not had any experience with Python’s async
, multiprocessing, or threading. For that, ask other Forum volunteers. Some have experience with one, two, or all three.
No no, I can absolutely use background tasks, but I am on an Education Plan, so my quotas are very limited, and I’d like my app to run successfully whenever my for-loop is called, and since my for-loop already runs during a background task, I don’t think that whipping up a number of background tasks, each background task for one loop, is going to be very server friendly.
I don’t want the Quota to be exceeded and all my loops crashing altogether.
Yeah, I tried to explore that angle as well, reading a bunch of posts on the Anvil forum.
But there are two problems with that: I don’t have a lot of experience with Async programming, and when I tried to ChatGPT it, and debug that code, it ended up not working at all.
I might revisit that angle in the future when I’m revising this project.
The problem is not on the number of background tasks, it’s on the amount of used resources.
Background tasks have some overhead over threads because they can use datatables and other services, but at the end of the day, if you exceed your quota with background tasks, you’re very likely to exceed it with threads too, because they are just a different way to consume memory and cpu. Processes are heavier than threads, and aren’t usable anyway.
Give it a try with background tasks, maybe you are right and your app will keep crashing, maybe you are wrong and everything will work just fine.
1 Like
Ok, will try that. Thanks for your help!
And as a fallback, remember, you can build your own background-task queue, via a database table, and do your own rate-limiting.