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

Going Over The Speed Limit - Synchronous Rendering in React Native

Tal Kol
September 06, 2017

Going Over The Speed Limit - Synchronous Rendering in React Native

* Given in React Native EU (Poland) on Sept 6, 2017

Asynchronous rendering is one of the core principles of React. On the web, the ability to batch updates and work on a virtual DOM proved to be key factors in improving rendering performance. The same architecture seems to do miracles in React Native and gives JavaScript the performance boost needed to render native views effectively.

This benefit of React Native is also its greatest drawback. For certain types of problems in native mobile, asynchronous rendering introduces an overhead that is almost impossible to bridge. List views are a good example, as even the best implementation to date, FlatList, struggles to keep up with the fill rate of the most naive list implementation in pure native.

Is it possible to introduce synchronous rendering to React Native and tackle this category of problems from a different direction?

Tal Kol

September 06, 2017
Tweet

More Decks by Tal Kol

Other Decks in Technology

Transcript

  1. Synchronous Rendering
    in React Native
    GOING OVER THE SPEED LIMIT
    TAL KOL Head of Mobile Engineering at Wix.com
    |

    View full-size slide

  2. @koltal
    Passionate about
    React Native at
    Hi.

    View full-size slide

  3. Performance,
    Are We There Yet?
    01

    View full-size slide

  4. The Pepsi Challenge
    WHICH ONE USES REACT NATIVE?

    View full-size slide

  5. Eliminating the gaps
    § Animations Declarative animations with Animated + native driver
    § Navigation Wix react-native-navigation + Airbnb native-navigation
    § Gestures Krzysztof Magiera’s new native gesture system
    § Interactions My react-native-interactable library from React Conf

    View full-size slide

  6. Flicker when
    pushing a new
    screen
    1

    View full-size slide

  7. Flicker when fast
    scrolling down
    lists (fill-rate)
    2

    View full-size slide

  8. Easy to Fix?
    APPARENTLY IT’S NOT SO SIMPLE
    The declarative trick doesn’t work here…
    An inherent issue with how React works

    View full-size slide

  9. To Block or
    Not To Block
    02

    View full-size slide

  10. The JavaScript
    Realm
    The Native
    Realm
    The Bridge
    React Native Architecture
    JavaScript
    Thread
    Main UI
    Thread

    View full-size slide

  11. Alternative 1: Blocking
    JavaScript
    Thread
    Main UI
    Thread
    A
    A
    B
    B

    View full-size slide

  12. Alternative 2: Non-Blocking
    JavaScript
    Thread
    Main UI
    Thread
    A
    A
    B
    B

    View full-size slide

  13. React for Web
    THE CHOICE HAS ALREADY BEEN MADE THEN
    Similar problem, DOM == native realm
    Performance gains by non-blocking (shadow DOM)

    View full-size slide

  14. React rendering is
    asynchronous by design

    View full-size slide

  15. User scrolls N pixels down the list
    Prepare New Row
    Scroll Event
    Create View
    Redraw Content
    New uninitialized row drawn as white space
    New row drawn with correct content
    React Render

    View full-size slide

  16. Circumventing
    Asynchronicity
    03

    View full-size slide

  17. RCTRootView
    React
    Component
    Tree

    View full-size slide

  18. RCTRootView API
    § create

    View full-size slide

  19. User pushes a new screen
    React Root Init
    Create Event
    Create Views
    Create RCTRootView
    New uninitialized screen drawn as white space
    New screen drawn with correct content
    React Render

    View full-size slide

  20. We want to support a
    synchronous root view

    View full-size slide

  21. RCTSyncRootView
    React
    Component
    Tree

    View full-size slide

  22. RCTSyncRootView API
    § create
    § update props

    View full-size slide

  23. User pushes a new screen
    Create Views
    Create RCTSyncRootView
    New screen drawn with correct content
    React Render
    JavaScript initialization (load)
    Magic Store Recipe
    Magic Use Recipe

    View full-size slide

  24. Synchronous render
    resolves the flicker!

    View full-size slide

  25. User scrolls N pixels down the list
    Prepare New Row
    Scroll Event
    Create View
    Redraw Content
    New uninitialized row drawn as white space
    New row drawn with correct content
    React Render

    View full-size slide

  26. User scrolls N pixels down the list
    Create View
    Recycle Old Row
    New row drawn with correct content
    React Render
    JavaScript initialization (load)
    Magic Store Recipe
    Magic Use Recipe

    View full-size slide

  27. Implementing The
    Magic Parts
    04

    View full-size slide

  28. Hacking the Reconciler
    TIME TO LOOK UNDER THE HOOD
    How does React render native views?
    We’ll use this process to create our recipe!

    View full-size slide

  29. render
    component

    View full-size slide

  30. Storing the Recipe
    ON JAVASCRIPT INITIALIZATION
    Manually call RN.render from SyncRegistry
    Swizzle UIManager funcs with store stubs

    View full-size slide

  31. render
    component

    View full-size slide

  32. Using the Recipe
    WHEN RCTSyncRootView IS CREATED OR UPDATED
    On demand, execute commands from native
    Instantiate native views without the bridge!

    View full-size slide

  33. Limitations
    § Only “declarative” components
    § No JavaScript code in render func
    § Prop updates can’t change the tree

    View full-size slide

  34. Proof of Concept
    Get Full Code
    github.com/wix/rn-synchronous-render

    View full-size slide

  35. Thanks.
    linkedin/talkol github.com/talkol
    @koltal
    [email protected]
    medium.com/@talkol
    @koltal

    View full-size slide