Hello,
I have got some process that creates up to 200 threads. (Managed by some other scripts and verified) this has worked to speed up these data processing.
My question is does invokeAsynchronous truly allow use of multiple cores or is it only using user controlled multi processing. A single one of the threads takes about 200 ms to complete. But sometime I see the threads total times increase as we process each thread in order. (Start at 200ms and then increase each thread following but not always by the total 200 ms)
The root of my question is what is the limit then? how many cores I have or the way in which the threads are handled for multi processing. Does it truly get access to run in all cores or only on a subset of the cores? Or even worse only access to one core as in the user defined abstraction of threading.
This is very technical heavy and more trying to understand how ignition works which scheduling threads.
Yes.
But whatever your algorithm does, especially if there are shared variables, can cause bottlenecks. Also, a common mistake is to include the parentheses for the background function when calling system.util.invokeAsynchronous()
. That causes the background function to run right then, and usually nothing is put in the background.
Show your code for more detailed assistance.
2 Likes
Thank you. This answered my question. This is what I figured but wanted a verification as well.
Also, the threads created by invokeAsynchronous are heavyweight OS threads. There's a non-trivial cost to their creation. If you're willing to trade off engineering effort, reaching into Java's primitives to create your own executor service with it's own managed threadpool can give you equivalent or better performance with reduced memory usage.
1 Like
I think this is a given but I want to confirm
.
Each system.util.invokeAsynchronous() call creates a new heavyweight OS thread, and does not re-use threads (i.e., there is no internal thread pool being used to minimize creation costs of threads)?
In which case using:
from java.util.concurrent import Executors
executor = Executors.newFixedThreadPool(20)
and storing the executor in the global dictionary
(with careful management to avoid memory leaks)
would be advantageous in cases where a loop is running many new threads.
Is that correct?
Yes, as long as the 20-thread limit introduce deadlock possibilities. The most effective number of threads might be higher if each thread has significant .sleep()
time, or time waiting on I/O.
1 Like
You could also, with some amount of effort, use the standard libraries' built in ForkJoinPool used for the CompletableFuture
API. If we were designing invokeAsynchronous
again from scratch, this is what we'd almost certainly use 'under the hood', but the function predates CompletableFuture
entirely.
1 Like