Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store interleaved updates on separate queue until end of render #20615

Merged
merged 1 commit into from
Jan 22, 2021

Commits on Jan 22, 2021

  1. Store interleaved updates on separate queue until end of render

    ## Motivation
    
    An *interleaved* update is one that is scheduled while a render is
    already in progress, typically from a concurrent user input event.
    
    We have to take care not to process these updates during the current
    render, because a multiple interleaved updates may have been scheduled
    across many components; to avoid tearing, we cannot render some of
    those updates without rendering all of them.
    
    ## Old approach
    
    What we currently do when we detect an interleaved update is assign a
    lane that is not part of the current render.
    
    This has some unfortunate drawbacks. For example, we will eventually run
    out of lanes at a given priority level. When this happens, our last
    resort is to interrupt the current render and start over from scratch.
    If this happens enough, it can lead to starvation.
    
    More concerning, there are a suprising number of places that must
    separately account for this case, often in subtle ways. The maintenance
    complexity has led to a number of tearing bugs.
    
    ## New approach
    
    I added a new field to the update queue, `interleaved`. It's a linked
    list, just like the `pending` field. When an interleaved update is
    scheduled, we add it to the `interleaved` list instead of `pending`.
    
    Then we push the entire queue object onto a global array. When the
    current render exits, we iterate through the array of interleaved queues
    and transfer the `interleaved` list to the `pending` list.
    
    So, until the current render has exited (whether due to a commit or an
    interruption), it's impossible to process an interleaved update, because
    they have not yet been enqueued.
    
    In this new approach, we don't need to resort to clever lanes tricks to
    avoid inconsistencies. This should allow us to simplify a lot of the
    logic that's currently in ReactFiberWorkLoop and ReactFiberLane,
    especially `findUpdateLane` and `getNextLanes`. All the logic for
    interleaved updates is isolated to one place.
    acdlite committed Jan 22, 2021
    Configuration menu
    Copy the full SHA
    c073037 View commit details
    Browse the repository at this point in the history