-
-
Notifications
You must be signed in to change notification settings - Fork 203
-
I have a function (see below) in a Quart app that counts prime numbers.
def count_primes_naive(n: int) -> int: """Count number of primes below some number.""" if n < 2: return 0 count = 0 for x in range(2, n + 1): is_prime = True for d in range(2, int(x**0.5) + 1): if x % d == 0: is_prime = False break if is_prime: count += 1 return count
I use this function in a route as shown here:
from quart import Quart from .primes import count_primes_naive app = Quart(__name__) @app.get("/count") async def count(): n = 1_000_000 p = count_primes_naive(n) return f"p is {p}"
Since the count_primes_naive function is not asynchronous, is the /count route still asynchronous?
Beta Was this translation helpful? Give feedback.
All reactions
count_primes_naive will be called synchronously and block. You should use run_sync.
Replies: 1 comment 8 replies
-
count_primes_naive will be called synchronously and block. You should use run_sync.
Beta Was this translation helpful? Give feedback.
All reactions
-
The requests are still going to take just as long, async does not make code faster. But when using run_sync, the long blocking function won't stop other requests from being handled in the meantime.
Beta Was this translation helpful? Give feedback.
All reactions
-
Yeah, I understand async will not make the code run faster. But I was expecting the requests/sec to be much higher when using run_sync for this particular example. Is there a better way to test this to show the difference between the two approaches?
Beta Was this translation helpful? Give feedback.
All reactions
-
run_sync is spawning a thread, and threads in Python still contend with the GIL. So since you're running something CPU intensive, you're still blocking to some degree. Use a subprocess executor instead for CPU intensive tasks. Unlike run_sync, the current request context can't be sent to subprocesses, so you'd need to send any arguments you need directly, but that's not relevant to the example given. Alternatively, you can attempt to run with Python's new free threading build, but I'm not sure whether that will work well with Hypercorn and Quart yet.
Beta Was this translation helpful? Give feedback.
All reactions
-
@davidism When you say "executor", are your referring to a ProcessPoolExecutor or ThreadPoolExecutor?
Beta Was this translation helpful? Give feedback.
All reactions
-
Use a subprocess executor instead
process
Beta Was this translation helpful? Give feedback.