Easily Faking I/O load for Reactive experiments

When investigating the benefits of Reactive Programming it is very useful to be able to simulate a heavy I/O load. This will help by enabling you to prove to yourself, and to others one of the major advantages of Reactive Programming, the fact that slow I/O does not block the CPU. This way your CPU can spend the I/O-wait-interval doing useful work like non I/O-bound web requests that require CPU-intensive calculations rather than just waiting and doing nothing.

Creating high CPU load is trivial, but actually simulating a heavy I/O load is not always that simple. We could fill up an async-ready database with data and then try to run incredibly inefficient queries on it. That will definitely slow down the database on the first call, but subsequent calls might hit a database cache instead. Even if we manage to be slow every call, it’s still rather unpredictable. Exact reproducibility can be a serious asset when doing deep investigation into the matter as well

A simple way to mimic slow I/O is by using Project Reactor’s delay method. It will make sure Reactor will stop for a given duration , after which its work continues. It also gives us the advantage of being able to dynamically control how long he exactly has to wait.

1
2
3
public Mono doAsyncSleep(int ms) {
    return Mono.delay(Duration.ofMillis(ms)).then();
}

However, this simple method feels a bit like cheating though, because in the end you’re not actually interfacing with I/O that way.

Another simple method is using MongoDB’s sleep  command (https://docs.mongodb.com/v3.0/reference/method/sleep/) . We can use it to stop the execution of the database for a given number of milliseconds. This way, we will be sure that an actual database call was made, and we can still reproduce the situation easily.

To do this, we use Spring Reactive Data’s ReactiveMongoTemplate class. Using the executeCommand method, we can make MongoDB’s Javascript interpreter evaluate a sleep command with a specified number of milliseconds.

1
2
3
public Mono doAsyncSleep(int ms) {
    return reactiveMongoTemplate.executeCommand(new Document("$eval", "sleep(" + ms +")")).then();
}

Of course any testing of an actual application requires you to test against a realistic dataset. However, when building a small Proof of Concept , or want to see for yourself how a reactive system will behave, these two methods are definitely something to be considered.