Running a graph asynchronously/multi-threaded
By default, the Map Graph Runner will run a graph synchronously, meaning that it will run on the main thread, preventing anything else from being run on the main thread until it's done. If the execution of a graph takes a really long time, it will freeze up your game or the Unity editor for the duration.
Run Asynchronously
To avoid any stuttering or freezes, you can enable asynchronous execution, which means that the graph will run on another thread (for as much as possible), which leaves room on the main thread for the game or Unity editor to keep running.
Another cause of stuttering might be the garbage collector running due to the garbage generated by Map Graph. In order to avoid this, you can enable object pooling
To enable asynchronous execution:
- Select the object with the Map Graph Runner component on it in the hierarchy window.
- Look for the Run Asynchronously option and enable it.
Caveats
While running graphs on another thread can be very useful, it comes with the important caveat that running asynchronously comes with some overhead, which can negatively impact the time it will take to run the graph.
This is mainly due to the fact that some nodes are dependent on the Unity API, which can only be called from the main thread. This means that whenever a call needs to be made to the Unity API, this call is put into a queue and further execution of the graph is halted until that call has been processed by the main thread.
Enable Multi-threading
In addition to running a graph asynchronously, it can be ran multi-threaded, meaning more than a single processor thread can be used to run a graph and therefore reducing the execution time in certain cases.
Enabling multi-threading will make Map Graph process multiple nodes at the same time (wherever possible).
To enable multi-threading:
- Select the object with the Map Graph Runner component on it in the hierarchy window.
- Look for the Run Asynchronously option and enable it.
- Look for the Enable Multi-threading option and enable it.
Which to use?
Whether you want to run your graph synchronously, asynchronously or multi-threaded depends on your project's needs and the complexity of your graph.
If your graph doesn't take a lot of time to run and isn't run at gameplay critical times, synchronous is probably fine and avoiding the overhead of the asynchronous options will likely result in faster execution times.
You should use asynchronous execution whenever you want to run a graph at gameplay critical times, that might cause stuttering or freezing. Asynchronous execution by itself is always slower than synchronous execution, due to the overhead.
Multi-threading will mostly benefit "tall" graphs, meaning graphs that don't mostly consist of nodes that only depend on the output of a single other node. (These types of graphs usually look visually taller in the graph editor.)
There's additional performance overhead to using multi-threading, so for graphs that aren't very "tall" it might actually hurt performance a bit and add unnecessary complexity, but for graphs that have a lot going on at the same time, this can reduce the processing time considerably.
If you simply want the fastest option, the choice is between synchronous or multi-threading. Asynchronous by itself will always be slower than synchronous. The best way to see which method is faster is to simply measure it. Running a graph in the editor will display the latest execution time in the inspector, which you can use to compare execution times.
Tracking progress
You can track the progress of the graph processing by hooking into the OnProgress event on the graph runner component.
graphRunner.OnProgress += (numberOfNodesProcess, totalNumberOfNodes) => {
Debug.Log("Processed " + numberOfNodesProcess + " out of " + totalNumberOfNodes);
};