Reactive Programming Advantages/Disadvantages
Asked Answered
S

8

52

I keep studying and trying Reactive Style of coding using Reactor and RxJava. I do understand that reactive coding makes better utilization of CPU compared to single threaded execution.

Is there any concrete comparison between reactive programming vs imperative programming in web based applications?

How much is the performance gain, throughput I achieve by using reactive programming over non-reactive programming?

Also what are the advantages and disadvantages of Reactive Programming?

Is there any statistical benchmark?

Spalla answered 6/2, 2017 at 7:14 Comment(2)
" I do understand that reactive coding makes better utilization of CPU compared to single threaded execution." That's not how it works. You got it right in the first sentence: "Style of coding".Collyrium
Virtual threads technology changes the calculus. See modern Answer by Thomas Schütt.Flori
C
49

Well, Reactive Programming means you are doing all your IO bound tasks such as network calls asynchronously. For an instance say your application calls an external REST API or a database, you can do that invocation asynchronously. If you do so your current thread does not block. You can serve lots of requests by merely spawning one or few threads. If you follow blocking approach you need to have one thread to handle each and every request. You may refer my multi part blog post part one, part two and part three for further details.

Other than that you may use callbacks to do the same. You can do asynchronous invocation using callbacks. But if you do so sometimes you may ended up with callback hell. Having one callback inside another leads to very complex codes which are very hard to maintain. On the other hand RxJava lends you write asynchronous code which is much more simple, composable and readable. Also RxJava provides you a lots of powerful operators such as Map, Zip etc which makes your code much more simple while boosting the performance due to parallel executions of different tasks which are not dependent on each other.

RxJava is not another Observer implementation with set of operators rather it gives you good error handling and retry mechanisms which are really handy.

But I have not conducted any bench marking of RxJava with imperative programming approach to commend you statistically. But I am pretty much sure RxJava should yield good performance over blocking mechanisms.

Update

Since I gathered more experience over time, I thought of adding more points to my answer.

Based on the article, ReactiveX is a library for composing asynchronous and event-based programs by using observable sequences. I reckon you to go through this introductory article in the first place.

These are some properties of reactive systems: Event Driven, Scalable, Resilient, Responsive

When it comes to RxJava it offers two main facilities to a programmer. First it offers a nice composable API using a rich set of operators such as zip, concat, map etc. This yields more simple and readable code. When it comes to code, readability and simplicity are the uttermost important properties. Second, it provides excellent abstractions, that enable concurrency to become declarative.

A popular misconception is that Rx is multithreaded by default. In fact, Rx is single-threaded by default. If you want to do things asynchronously, then you have to tell it explicitly using subscribeOn and observeOn operators by passing relevant schedulers. RxJava gives you thread pools to do asynchronous tasks. There are many schedulers such as IO, Computation and so forth. IO scheduler as the name suggests is best suited for IO intensive tasks such as network calls etc. on the contrary, Computation scheduler is good for more CPU intensive computation tasks. You can also hook up your own Executor services with RxJava too. The built in schedulers mainly helps you to get rid of maintaining your own Executor services, making your code more simple.

Finally a word on subscribeOn and observeOn

In the Rx world, there are generally two things you want to control the concurrency model for:

  1. The invocation of the subscription
  2. The observing of notifications

SubscribeOn: specify the Scheduler on which an Observable will operate.

ObserveOn: specify the Scheduler on which an observer will observe this Observable

Cretin answered 6/2, 2017 at 7:45 Comment(0)
B
14

Disadvantages

  • More memory intensive to store streams of data most of the times (since it is based on streams over time).
  • Might feel unconventional to learn at start(needs everything to be a stream).
  • Most complexities have to be dealt with at the time of declaration of new services.
  • Lack of good and simple resources to learn.

  • Often confused to be equivalent to Functional Reactive Programming.

Beckon answered 29/8, 2017 at 12:0 Comment(8)
How are you differentiating between Reactive Programming and Functional Reactive Programming? What qualities are you considering to be different between the two?Kristie
if everything is a stream with a lot of operators on it it can be harder to understand than simple imperative code.Batch
@NovemberYankee this would need a separate post to be honest. FRP is in a way a super set of Reactive programming and the way things are done using FRP differs in ways the same operation is achieved using Reactive Programming. Pure functions,etc come into picture with FRP, which is not a necessity with reactive programming.Beckon
@Batch It as I mentioned might be difficult initially to wrap around your head, but these operators simplify and reduce the amount of code for a lot of things you would otherwise have to do yourself.Beckon
at times its useful. I wouldnt go over kill with lots of operators. it takes away from the readabbilty. i want the codebase to be simple to readBatch
also using rx in every layer of the app isnt a good idea. I try react to backend or cache events only.Batch
+X times more difficult to understand the existing code (even written by yourself). +X times more time spent on debugging (no stacktrackes for example, forget about undestanding how the existing app work by analysing them). Transactional consistency, hmm... From the business point of view +X times more expensive, because takes a lot more of development/maintenance time. I'm wondering if there's a comparison anywhere about ROI from reactive programming. I mean a lot more money on expensive developers, at the same time making some savings on relatively cheap iron :)Foreshank
Hi , todays days ,is there still lack of good and simple resources to learn?Wifely
S
9

Apart of what is already mentioned in other responses regarding no blocking features, another great feature about reactive programing is the important use of backpressure. Normally it is used in situations where your publisher emits more information than your consumer can process.

So having this mechanism you can control the flow of traffic between both and avoid nasty out of memory problems.

You can see some practical examples of reactive programming here: https://github.com/politrons/reactive

And about back pressure here: https://github.com/politrons/Akka/blob/master/src/main/scala/stream/BackPressure.scala

By the way, the only disadvantage about reactive programming, is the learning curve because you're changing the programming paradigm. But nowadays all important companies respect and follow the reactive manifesto.

Shearwater answered 6/2, 2017 at 8:47 Comment(0)
J
4

Reactive Programming is a style of micro-architecture involving intelligent routing and consumption of events.

Reactive is that you can do more with less, specifically you can process higher loads with fewer threads.

Reactive types are not intended to allow you to process your requests or data faster.Their strength lies in their capacity to serve more request concurrently, and to handle operations with latency, such as requesting data from a remote server, more efficiently.

They allow you to provide a better quality of service and a predictable capacity planning by dealing natively with time and latency without consuming more resources.

From
https://blog.redelastic.com/what-is-reactive-programming-bc9fa7f4a7fc https://spring.io/blog/2016/06/07/notes-on-reactive-programming-part-i-the-reactive-landscape https://spring.io/blog/2016/07/28/reactive-programming-with-spring-5-0-m1

Jilolo answered 23/10, 2017 at 8:42 Comment(0)
E
1

Using non blocking reactive programming model can save memory usage. For example, with the traditional blocking model style programming model in spring boot

@GetMapping
public List<Customer> getCustomers(){
  List<Customers> customerList = customerRepository.findAlll()

This code can cause out of heap memory error if the number of records are too high(2 millions). But using reactive programming style, the lists of customers with 2 millions records are released fine (you can use backpressure techniques to reduce loading speed in the front end)

@GetMapping("/")
public Flux<Customer> getCustomers() {
    return customerRepository.findAll()
            .doOnNext(customer -> System.out.println(customer.getCustomerName()));
}
Encourage answered 5/2, 2024 at 0:15 Comment(0)
S
1

Virtual threads

Since Java 21 with its cheap virtual threads the one exclusive plus of reactive programming (namingly not to consume lots of expensive native threads caused by slow IO) is not existent any more.

See video of Brian Goetz being asked what he sees as the future of reactive programming after the arrival of Project Loom and virtual threads:

I think Loom is going to kill reactive programming … reactive programming was a transitional technology …

I am curious to see what will happen to reactive programming, at least in the JVM world. Not being able to use ThreadLocal is a big minus of reactive programming.

Stroganoff answered 3/7, 2024 at 11:37 Comment(2)
Plus (a) the cognitive burden of reading reactive coding versus straightforward linear code in virtual threads, and (b) nearly impossible debugging in reactive versus the simple debugging in virtual threads using the usual tooling.Flori
See related Question: Do Java 21 virtual threads address the main reason to switch to reactive single-thread frameworks?Flori
A
0

Advantages

  1. Cleaner code, more concise
  2. Easier to read (once you get the hang of it)
  3. Easier to scale (pipe any operation)
  4. Better error handling
  5. Event-driven inspired -> plays well with streams (Kafka, RabbitMQ,etc)
  6. Backpressure (client can control flow)

Disadvantages

  1. Can become more memory intensive in some cases
  2. Somewhat steep learning curve
Arguable answered 6/7, 2019 at 19:59 Comment(3)
Cleaner code and easier to read is arguable. It is not cleaner or easier to read than using Java Util Streams. The error handling is IMHO not better than the traditional try-catch-finally, which is also easier to read.Deathbed
I agree with @YounesElOuarti - cleanliness, conciseness, and readability are not an advantage IMHO. I've been coding a reactive backend for the past 10 months. I can say that when it comes to simple implementation of logic then it's fine, but when you start coding logic which is more complex, it becomes a bit hellish even for someone who is familiar with reactive programming. It becomes a lot more difficult when you onboard to the team someone who has never worked with reactive code. Unless I absolutely require non-blocking code for high scale/performance, I wouldn't go down the reactive pathFluoroscopy
It is definitely not a cleaner code, most code implemented with reactive programming look like an unending chaining of methods and let's not even go into trying to debug something written with reactive programming, I wouldn't wish that on my worst enemy.Marketplace
P
-7

Reactive programming is a kind of imperative programming. Reactive programming is a kind of parallel programming. You can achieve performance gain over single threaded execution only if you manage to create parallel branches. Will they executed by multiple threads, or by reactive constructs (which in fact are asynchronous procedures), does not matter.

The single advantage of reactive programming over multithreaded programming is lower memory consumption (each thread requires 0.5...1 megabyte). The disadvantage is less easy programming.

UPDATE (Aug 2020). Parallel programming can be of 2 flavours: mulithreaded programming, where main activity is thread, and asynchronous programming, where main kind of activity is asynchronous procedure (including actors, which are repeatable asynchronous procedures). In mulithreaded programming, various means of communication are used: unbounded queues, bounded (blocking) queues, binary and counting semaphores, countdownLatches and so on. Moreover. there is always possiblity to create your own mean of communication. In asynchronous programming, until recently, only 2 kinds of communicators were used: future for non-repeatable asynchronous procedures, and unbounded queue for actors. Unbounded queue causes problems when producer works faster than consumer. To cope with this problem, new communication protocol was invented: reactive stream, which is combination of unbounded queue and counting (asynchronous) semaphore to make the queue bounded. This is direct analogue to the blocking queue in multithreaded programming. And programming with reactive streams was proudly called Reactive Programming (imagine, if in multithreded programming, programming with blocking queues was called Blocking Programming). But again, no means to create own communication tools were provided to asynchronous programmer. And the asynchronous semaphore cannot be used in its own, only as part of reactive stream. That said, the theory of asynchronous programming, including theory of reactive programming, lags far behind the theory of multithreded programming.

A fancy addition to reactive streams is mapping/filtering functions allowing to write linear piplines like

 publisher
     .map(()->mappingFunction)
     .filter(()->filterFunction)
     .flatmap(...)

etc. But this is not an exclusive feature of reactive programming. And this allows to create only linear piplines, while in multithreaded programming it is easy to create computational graphs of arbitrary topology.

 

Phio answered 2/11, 2018 at 17:47 Comment(10)
This answer is completely inaccuratePapaya
@Papaya this answer contradicts to the the general beliefs, but is absolutely accurate. Just the time has not come. Once upon a time, people thought the Earth is flat and the Sun revolves around the Earth.Phio
The third sentence contradicts the second.Papaya
The last sentence of the first paragraph makes no sense. The sentence about memory consumption is pure nonsense. Threads don't take 0.5-1mb.Papaya
Reactive programming is declarative not imperative and can be used with either declarative or imperative programming paradigms. Reactive programming can be used in single or multithreaded code.Papaya
"Threads don't take 0.5-1mb" - they could take even more: man7.org/linux/man-pages/man3/pthread_create.3.htmlPhio
Thread stack allocation is processor and operating system dependent. Ranging from 1mb to 10mb. However, the CPU only allocates the memory when the thread needs it. See this answer for more details: unix.stackexchange.com/a/280865/125333Papaya
Memory limits are pretty moot in this context but the number of them may be more important. Take a look at Thread Pooling.Papaya
@Papaya I'd say it actually provides correct information by stating the opposite of itBreakfront
I wouldn't say this answer is completely inaccurate. It's just that along with some useful information, it has a biased rant against reactive programming giving the answer a feeling of biased opinion.Orpah

© 2022 - 2025 — McMap. All rights reserved.