Batching executions of suspend function

Hi, I have a scenario that requires batching computations and distributing them to a grid. I’m wondering whether it could be solved by continuation in Kotlin.

Here’s my use case. Let’s say I have a number of trades to price (the number could vary from 1 to 100k):

… //some logic to resolve trades
val results = trades.map{it.pv()}
… // post process results

pv is a chain of computations and IOs and different trades might depend on different algorithms (code path). In addition, the computation time for different trade also varies from 10 millis to 10 seconds.

If the number of trades is small, they could run within a single machine. However, when the number is large, we need put them into different batch and distribute each batch to a remote node for computation.

The model of computation is illustrated as above diagram (very much simplified). ‘pv’ calls ‘price’ through a chain of computations and all of them are suspend function and executed by coroutines asynchronously.

Ideally I want to batch ‘price’ functions in the end because only at this point all algorithms are decided and data is prepared. Moreover, the batch and non-batch logic should be orthogonal which means I should be able to enable/disable the batcher without changing existing biz logic.

Conceptually it looks like making ‘price’ function optionally depend on another batch function as its continuation.

In my past project, we had similar runtime called dependency graph, in which each node is a function and edges between nodes are function calls. These nodes are like suspend functions and there’s a runtime scheduler to execute nodes asynchronously based on their dependencies. It’s very much like coroutine and implemented using continuations as well. Being said that, we implement above batching feature by having a scheduler plugin. In case of a batcher plugin is set, the scheduler at runtime make the original function depend on the batched function and all these is transparent to the user like below code:

class Algo {
fun price(…):PV {…} // function trade.pv depends on
}

class AlgoBatcher {

fun run(price_functions:List<Function>):List<PV> { .... } // grouping and distribution here

}

Algo.price.plugin = AlgoBatcher()

val results = trades.map{it.pv()} // in case a batcher is set, it will distribute them to the grid

Is it possible to achieve something like this in Kotlin?

1 Like