Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

Moscow JUG
December 13, 2018

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

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

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

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

Moscow JUG

December 13, 2018
Tweet

More Decks by Moscow JUG

Other Decks in Programming

Transcript

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

    психанули, и реализовываете свою реактивную библиотеку / Вам хочется понять как оно работает / Вы просто любите хардкора
  2. / 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]); } } }
  3. / Oleh Dokuka 10 Реактивный Хардкор Потому что спека 100500

    41 https://github.com/reactive-streams/reactive-streams-jvm/blob/v1.0.2/README.md#specification
  4. / Oleh Dokuka 11 Реактивный Хардкор Все по порядку /

    onSubscribe() 1 / onNext() 0..N / onError | onComplete() 1
  5. / Oleh Dokuka 12 Реактивный Хардкор Сколько request() столько и

    onNext() request(5) { onNext(a) onNext(b) onNext(c) onNext(d) onNext(e) }
  6. / Oleh Dokuka 18 Work in Progress (WIP) Title Text

    Title Text Предотвращаете бесконечную рекурсию: request(onNext(request(onNext…))))
  7. / Oleh Dokuka 20 Реактивный Хардкор Итожим / Работает /

    Тесты проходят / Немного сложно
  8. / 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
  9. / 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
  10. / 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
  11. / 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
  12. / 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
  13. / 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
  14. / 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
  15. / 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
  16. / 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
  17. / 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
  18. / 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
  19. / 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
  20. / 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
  21. / 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
  22. / 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 Реактивный Хардкор
  23. / Oleh Dokuka 42 WIP + Infinite Loop Реактивный Хардкор

    Для того что бы WIP работал хорошо во время многопоточной гонки
  24. / Oleh Dokuka 46 Реактивный Хардкор Оптимизируем / Доступ к

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

    работа в прогрессе / бесконечный цикл / fastPath / slowPath / AtomicXXXFieldUpdater
  26. / Oleh Dokuka 54 Реактивный Хардкор Итог / Ничего страшного

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