There are 2 types of splitters, a in-memory only blocking splitter, whose arms must be read asynchronously otherwise it will block until the lagging arms catch up, and a spilling variety.
The decision as to whether it's a spilling kind or not is determined by the code generator, and dependent on the pattern of pulling of the downstream activities. The idea being that you want to avoid spilling.
In the case of a blocking splitter and there are blocking problems (generally due to some underlying bug), it is very difficult to see what is blocked in a complex graph with e.g. many splitters and async threads.
It would be helpful if a blocking splitter detected a stall and started logging information under those circumstances to pinpoint the area.