Олег Докука — Реактивный Хардкор

3fc5b5eb32bd3b48d7810fd67b37f9a1?s=47 Moscow JUG
December 13, 2018

Олег Докука — Реактивный Хардкор

Разрабатываете свою библиотеку? Решили поддерживать Reactive-Streams specification? Хотите понять, что творится под капотом у RxJava 2 или Reactor 3? Либо же вы любитель хардкора? Тогда этот доклад для вас!

Во время доклада мы затронем причины создания спецификации Reactive-Streams и сложность в работе с ней. Как первый шаг — создадим наивную реализацию интерфейсов, посмотрим, где же напортачили, как протестить корректность. Шаг за шагом мы доберемся до правды и пройдем через все испытания в разработке операторов. В результате вынесем лучшие практики в реализации таких зверей, разберем, что, как и зачем, на пальцах и убедимся, что именно так всё и работает в модерных библиотеках, таких как RxJava 2 и Reactor 3.

После этого доклада у вас будет понимание того, как создать и протестировать свой оператор. Вдобавок у вас будет более четкое понимание того, как устроены реактивные библиотеки. Также вы увидите сложности конкуретной разработки и поймете, как с этим жить.

3fc5b5eb32bd3b48d7810fd67b37f9a1?s=128

Moscow JUG

December 13, 2018
Tweet

Transcript

  1. 2.

    / Oleh Dokuka 2 Реактивный Хардкор Для кого? / Вы

    психанули, и реализовываете свою реактивную библиотеку / Вам хочется понять как оно работает / Вы просто любите хардкора
  2. 4.
  3. 9.

    / Oleh Dokuka Реактивный Хардкор 9 public interface Publisher<T> {

    private final T[] source; public ArrayPublisher(T[] source) { this.source = source; } @Override public void subscribe(Subscriber<? super T> subscriber);{ for (int i = 0; i < source.length; i++) { subscriber.onNext(source[i]); } } } public class ArrayPublisher<T> implements Publisher<T> { private final T[] source; public ArrayPublisher(T[] source) { this.source = source; } @Override public void subscribe(Subscriber<? super T> subscriber) { for (int i = 0; i < source.length; i++) { subscriber.onNext(source[i]); } } } public class ArrayPublisher<T> implements Publisher<T> { private final T[] source; public ArrayPublisher(T[] source) { this.source = source; } @Override public void subscribe(Subscriber<? super T> subscriber) { for (int i = 0; i < source.length; i++) { subscriber.onNext(source[i]); } } }
  4. 10.

    / Oleh Dokuka 10 Реактивный Хардкор Потому что спека 100500

    41 https://github.com/reactive-streams/reactive-streams-jvm/blob/v1.0.2/README.md#specification
  5. 11.

    / Oleh Dokuka 11 Реактивный Хардкор Все по порядку /

    onSubscribe() 1 / onNext() 0..N / onError | onComplete() 1
  6. 12.

    / Oleh Dokuka 12 Реактивный Хардкор Сколько request() столько и

    onNext() request(5) { onNext(a) onNext(b) onNext(c) onNext(d) onNext(e) }
  7. 14.
  8. 18.

    / Oleh Dokuka 18 Work in Progress (WIP) Title Text

    Title Text Предотвращаете бесконечную рекурсию: request(onNext(request(onNext…))))
  9. 20.

    / Oleh Dokuka 20 Реактивный Хардкор Итожим / Работает /

    Тесты проходят / Немного сложно
  10. 26.

    / Oleh Dokuka Реактивный Хардкор 26 AtomicLong requested = new

    AtomicLong(); @Override public void request(long n) { long initialRequested = requested.getAndAdd(n); if (initialRequested > 0) { return; } for (...) { ... } ... requested.addAndGet(-sent); } 0 0 0
  11. 27.

    / Oleh Dokuka Реактивный Хардкор 27 AtomicLong requested = new

    AtomicLong(); @Override public void request(long n) { long initialRequested = requested.getAndAdd(n); if (initialRequested > 0) { return; } for (...) { ... } ... requested.addAndGet(-sent); } 0 0 0
  12. 28.

    / Oleh Dokuka Реактивный Хардкор 28 5 0 AtomicLong requested

    = new AtomicLong(); @Override public void request(long n) { long initialRequested = requested.getAndAdd(n); if (initialRequested > 0) { return; } for (...) { ... } ... requested.addAndGet(-sent); } 0
  13. 29.

    / Oleh Dokuka Реактивный Хардкор 29 AtomicLong requested = new

    AtomicLong(); @Override public void request(long n) { long initialRequested = requested.getAndAdd(n); if (initialRequested > 0) { return; } for (...) { ... } ... requested.addAndGet(-sent); } 5 0 0
  14. 30.

    / Oleh Dokuka Реактивный Хардкор 30 AtomicLong requested = new

    AtomicLong(); @Override public void request(long n) { long initialRequested = requested.getAndAdd(n); if (initialRequested > 0) { return; } for (...) { ... } ... requested.addAndGet(-sent); } 5 0 0
  15. 31.

    / Oleh Dokuka Реактивный Хардкор 31 AtomicLong requested = new

    AtomicLong(); @Override public void request(long n) { long initialRequested = requested.getAndAdd(n); if (initialRequested > 0) { return; } for (...) { ... } ... requested.addAndGet(-sent); } 5 0 5
  16. 32.

    / Oleh Dokuka Реактивный Хардкор 32 AtomicLong requested = new

    AtomicLong(); @Override public void request(long n) { long initialRequested = requested.getAndAdd(n); if (initialRequested > 0) { return; } for (...) { ... } ... requested.addAndGet(-sent); } 0 0 5
  17. 33.

    / Oleh Dokuka Реактивный Хардкор 33 AtomicLong requested = new

    AtomicLong(); @Override public void request(long n) { long initialRequested = requested.getAndAdd(n); if (initialRequested > 0) { return; } for (...) { ... } ... requested.addAndGet(-sent); } 0 0 0
  18. 34.

    / Oleh Dokuka Реактивный Хардкор 34 AtomicLong requested = new

    AtomicLong(); @Override public void request(long n) { long initialRequested = requested.getAndAdd(n); if (initialRequested > 0) { return; } for (...) { ... } ... requested.addAndGet(-sent); } 5 0 0
  19. 35.

    / Oleh Dokuka Реактивный Хардкор 35 AtomicLong requested = new

    AtomicLong(); @Override public void request(long n) { long initialRequested = requested.getAndAdd(n); if (initialRequested > 0) { return; } for (...) { ... } ... requested.addAndGet(-sent); } 5 0 1
  20. 36.

    / Oleh Dokuka Реактивный Хардкор 36 AtomicLong requested = new

    AtomicLong(); @Override public void request(long n) { long initialRequested = requested.getAndAdd(n); if (initialRequested > 0) { return; } for (...) { ... } ... requested.addAndGet(-sent); } 5 0 5
  21. 37.

    / Oleh Dokuka Реактивный Хардкор 37 AtomicLong requested = new

    AtomicLong(); @Override public void request(long n) { long initialRequested = requested.getAndAdd(n); if (initialRequested > 0) { return; } for (...) { ... } ... requested.addAndGet(-sent); } 10 5 5
  22. 38.

    / Oleh Dokuka Реактивный Хардкор 38 AtomicLong requested = new

    AtomicLong(); @Override public void request(long n) { long initialRequested = requested.getAndAdd(n); if (initialRequested > 0) { return; } for (...) { ... } ... requested.addAndGet(-sent); } 5 5 5
  23. 39.

    / Oleh Dokuka Реактивный Хардкор 39 AtomicLong requested = new

    AtomicLong(); @Override public void request(long n) { long initialRequested = requested.getAndAdd(n); if (initialRequested > 0) { return; } for (...) { ... } ... requested.addAndGet(-sent); } 5 5 0
  24. 40.

    / Oleh Dokuka 40 AtomicLong requested = new AtomicLong(); @Override

    public void request(long n) { long initialRequested = requested.getAndAdd(n); if (initialRequested > 0) { return; } for (...) { ... } ... requested.addAndGet(-sent); } 5 5 0 Реактивный Хардкор
  25. 42.

    / Oleh Dokuka 42 WIP + Infinite Loop Реактивный Хардкор

    Для того что бы WIP работал хорошо во время многопоточной гонки
  26. 46.

    / Oleh Dokuka 46 Реактивный Хардкор Оптимизируем / Доступ к

    переменным / Количество атомарных оп-ий / Количество созданных объектов / Путь выполнения
  27. 53.

    / Oleh Dokuka 53 Реактивный Хардкор Паттерны / WIP -

    работа в прогрессе / бесконечный цикл / fastPath / slowPath / AtomicXXXFieldUpdater
  28. 54.

    / Oleh Dokuka 54 Реактивный Хардкор Итог / Ничего страшного

    нету / Все для скорости и низкой задержки / TCK - помогает, но кое-что сами / Мойте руки после говно-кода