Osservabile vs Flowable rxJava2


128

Ho guardato il nuovo rx java 2 e non sono abbastanza sicuro di aver capito più l'idea di backpressure...

Sono consapevole che abbiamo Observableche non ha backpressuresupporto e Flowableche ce l' ha.

Quindi, sulla base di un esempio, diciamo che ho flowablecon interval:

        Flowable.interval(1, TimeUnit.MILLISECONDS, Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Consumer<Long>() {
                @Override
                public void accept(Long aLong) throws Exception {
                    // do smth
                }
            });

Questo andrà in crash dopo circa 128 valori, ed è abbastanza ovvio che sto consumando più lentamente che ottenere oggetti.

Ma poi abbiamo lo stesso con Observable

     Observable.interval(1, TimeUnit.MILLISECONDS, Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Consumer<Long>() {
                @Override
                public void accept(Long aLong) throws Exception {
                    // do smth
                }
            });

Questo non si bloccherà affatto, anche quando metto un po 'di ritardo nel consumo, funziona ancora. Per far Flowablefunzionare, diciamo che metto onBackpressureDropoperator, crash è sparito ma non tutti i valori vengono emessi.

Quindi la domanda di base che non riesco a trovare risposta attualmente nella mia testa è perché dovrei preoccuparmi di backpressurequando posso usare plain Observableancora ricevere tutti i valori senza gestire il buffer? O forse dall'altro lato, quali vantaggi mi backpressuredanno a favore della gestione e della gestione del consumo?


Risposte:


123

Ciò che la contropressione si manifesta in pratica sono i buffer limitati, Flowable.observeOnha un buffer di 128 elementi che viene drenato alla velocità con cui il flusso d'aria può sopportarlo. È possibile aumentare questa dimensione del buffer individualmente per gestire la sorgente bursty e tutte le pratiche di gestione della contropressione si applicano ancora da 1.x. Observable.observeOnha un buffer illimitato che continua a raccogliere gli elementi e la tua app potrebbe esaurire la memoria.

Puoi usare Observablead esempio:

  • gestione degli eventi della GUI
  • lavorare con sequenze brevi (meno di 1000 elementi in totale)

Puoi usare Flowablead esempio:

  • sorgenti fredde e non temporizzate
  • generatore come sorgenti
  • accessori di rete e database

Dal momento che questo ha messo a punto in un'altra domanda - è vero che i tipi più ristretti come Maybe, Singlee Completablepuò sempre essere usato al posto di Flowablequando sono semanticamente appropriato?
david.mihola

1
Sì, Maybe, Single, e Completablesono di gran lunga troppo piccolo per avere qualsiasi esigenza del concetto contropressione. Non c'è alcuna possibilità che un produttore possa emettere oggetti più velocemente di quanto possano essere consumati, dal momento che 0-1 oggetti saranno mai prodotti o consumati.
AndrewF

Forse non ho ragione, ma per me gli esempi di Flowable e Observable dovrebbero essere scambiati.
Yura Galavay

Penso che nella domanda gli manchi la strategia di contropressione che dobbiamo fornire al Flowable, il che spiega perché viene lanciata l'eccezione di contropressione mancante, spiega anche perché questa eccezione scompare dopo aver applicato .onBackpressureDrop (). E per Observable, poiché non ha questa strategia e non può essere fornita, semplicemente fallirà in seguito a causa di OOM
Haomin

111

La contropressione si verifica quando il tuo osservabile (editore) crea più eventi di quanti il ​​tuo abbonato possa gestire. In questo modo puoi far sì che gli abbonati perdano eventi o puoi ottenere un'enorme coda di eventi che alla fine porta alla mancanza di memoria. Flowableprende in considerazione la contropressione. Observablenon. Questo è tutto.

mi ricorda un imbuto che quando ha troppo liquido trabocca. Flowable può aiutare a non farlo accadere:

con un'enorme contropressione:

inserisci qui la descrizione dell'immagine

ma con l'utilizzo di flowable, c'è molta meno contropressione:

inserisci qui la descrizione dell'immagine

Rxjava2 ha alcune strategie di contropressione che puoi utilizzare a seconda del tuo caso d'uso. per strategia intendo che Rxjava2 fornisce un modo per gestire gli oggetti che non possono essere elaborati a causa dell'overflow (contropressione).

ecco le strategie. Non li esaminerò tutti, ma ad esempio, se non vuoi preoccuparti degli elementi traboccati, puoi utilizzare una strategia di rilascio come questa:

observable.toFlowable (BackpressureStrategy.DROP)

Per quanto ne so dovrebbe esserci un limite di 128 elementi sulla coda, dopodiché potrebbe esserci un overflow (contropressione). Anche se non è 128, è vicino a quel numero. Spero che questo aiuti qualcuno.

se hai bisogno di cambiare la dimensione del buffer da 128 sembra che possa essere fatto in questo modo (ma fai attenzione ai vincoli di memoria:

myObservable.toFlowable(BackpressureStrategy.MISSING).buffer(256); //but using MISSING might be slower.  

nello sviluppo del software di solito la strategia di contropressione significa che stai dicendo all'emettitore di rallentare un po 'poiché il consumatore non può gestire la velocità dei tuoi eventi di emissione.


Ho sempre pensato che la contropressione fosse il nome di una famiglia di meccanismi che consentirebbero al consumatore di avvisare il produttore di rallentare ...
kboom

Potrebbe essere il caso. Sì
j2emanue

Ci sono degli svantaggi nell'usare un Flowable?
IgorGanapolsky

Queste immagini mi stanno mentendo. Eliminare gli eventi non finirà con "più soldi" sul fondo.
EpicPandaForce

1
@ j2emanue, stai confondendo la dimensione del buffer per gli operatori e l'operatore Flowable.buffer (int). Si prega di leggere attentamente i javadoc e di correggere la risposta di conseguenza: reattivex.io/RxJava/2.x/javadoc/io/reactivex/Flowable.html
tomek

15

Il fatto che si sia verificato un Flowablearresto anomalo dopo aver emesso 128 valori senza la gestione della contropressione non significa che si bloccherà sempre dopo esattamente 128 valori: a volte si arresta in modo anomalo dopo 10, ea volte non si arresta affatto. Credo che questo sia quello che è successo quando hai provato l'esempio con Observable: non c'era contropressione, quindi il tuo codice ha funzionato normalmente, la prossima volta potrebbe non esserci. La differenza in RxJava 2 è che non esiste più il concetto di contropressione in Observables e non c'è modo di gestirlo. Se stai progettando una sequenza reattiva che probabilmente richiederà una gestione esplicita della contropressione, questa Flowableè la scelta migliore.


Sì, ho osservato che a volte si è rotto dopo meno valori, a volte no. Ma ancora una volta, se per esempio sto gestendo solo intervalsenza backpressure, mi aspetterei qualche comportamento o problemi strani?
user2141889

Se sei sicuro che non sia possibile che si verifichino problemi di contropressione in una specifica sequenza osservabile, immagino che sia giusto ignorare la contropressione.
Egor
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.