Skip to content

JS: Set timeout dispatcher performance issues on react native #4561

@trema96

Description

@trema96

Summary

On React Native the default dispatcher is the SetTimeoutDispatcher, which schedules the queue processing as a js macrotask using setTimeout(0).

I think this does not align with the implementations of the other dispatchers, which schedule the queue processing using process.nextTick on node and use an already resolved promise (Promise.resolve(Unit).then({ process() }), therefore a microtask) on browser.

The observable effect is that something as simple as:

repeat(10_000) { t ->
	(js("Promise.resolve(t)") as Promise<Int>).await()
}

which is almost instantaneous on browser and node (~100ms and ~20ms on my machine), takes minutes on react native (2m45s on my machine, running a sample expo app on ios simulator).

Proposed solution

From what I read in the react native documentation I think setImmediate might be the best fit for a dispatcher specifically for react native.

NativeScript

I focused on the issue on react native as the issue is directly affecting me on that platform, but wouldn't NativeScript also have a similar issue? Is there a reason why the current SetTimeoutDispatcher can't use Promise.resolve(Unit).then({ process() })?

Yielding to macrotask

Implementing a dispatcher using setImmediate would prevent the code in my above example (awaiting already resolved promises) from yielding to the macrotask event loop until finished.

I think this is the appropriate behaviour, as it is the same behaviour as on the current dispatcher for browser, and is the same behaviour for equivalent javascript code:

    async function doProcess() {
        for (let i = 0; i <= 10_000; i++) {
            await Promise.resolve()
            // Will not actually show intermediate progress, rerender is not triggered until doProcess is finished.
            document.getElementById('progressText').innerText = "Progress: " + i
        }
    }

However this is different from the SetTimeoutDispatcher, which schedules the queue processing as a macrotask, and therefore the proposed change might be breaking for some applications.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions