🧵 Fast and easy multithreading for React Native using JSI

Overview

react-native-multithreading

🧵 Fast and easy multithreading for React Native using JSI.


Buy Me a Coffee at ko-fi.com


Installation

npm install react-native-multithreading
npx pod-install

Requires a version of react-native-reanimated which includes PR #1790. Either patch it yourself, or wait until that lands in a release.

⚠️ Warning: This is still just a proof of concept - do not use this library in production! ⚠️

Why

Since JSI is becoming more mainstream, there might be functions that are actually blocking and take a while to execute. For example, a storage library like my react-native-mmkv or an SQLite JSI library might take a few milliseconds to execute a complex call. You don't want your entire React-JS thread to freeze when doing that, since users will perceive a noticeable lag or freeze.

That's where react-native-multithreading comes in; you can simply off-load such expensive calculations/blocking calls to a separate thread with almost no overhead while your main React-JS thread can concentrate on running your app's business logic, respond to user input, update state and more. You can also run complex JS calculations such as the Fibonacci number, but that's probably a rare use-case.

Inspired by @karol-bisztyga's Multithreading PR for Reanimated

Usage

To try out the Fibonacci Example, clone the repo and run the following commands:

yarn bootstrap
cd example
yarn ios

See my tweet 🐦

Shoot and Forget

To simply perform an expensive calculation on another thread without caring about the result, use the spawnThread function:

// JS thread
spawnThread(() => {
  'worklet'
  // custom thread
  // expensive calculation
})
// JS thread

The React-JS Thread will continue execution while the custom thread will run the given function on a custom parallel runtime.

Await

Since spawnThread returns a Promise, you can also await the result. The React-JS Thread will not be blocked and will still be able to continue execution elsewhere (timers, callbacks, ...), while the custom thread runs the given function in a custom parallel runtime.

const result = await spawnThread(() => {
  'worklet'
  // expensive calculation
  return ...
})

Fibonacci

This example calculates the Fibonacci Number for the given input. This demonstrates expensive calculation, awaiting the result, as well as using values from "outside". (fibonacci function and input are captured into the new thread and therefore immutable.)

const fibonacci = (num: number): number => {
  'worklet'
  if (num <= 1) return 1
  return fibonacci(num - 1) + fibonacci(num - 2)
}

const input = 50
const result = await spawnThread(() => {
  'worklet'
  console.log(`calculating fibonacci for input: ${input} in JS-Runtime: ${global._LABEL}...`)
  const fib = fibonacci(input)
  console.log("finished calculating fibonacci!")
  return fib
})
console.log(`Fibonacci Result: ${result}`)

What's possible?

  • You can use variables from "outside" (e.g. state), but those will be immutable/frozen.
  • You can use functions from "outside" if they also contain the 'worklet' directive.
  • You can assign Reanimated Shared Values.
  • You can call native JSI functions ("Host Functions") from a JSI library, e.g. every function react-native-mmkv provides.
  • You can asynchronously dispatch calls to functions from "outside" using runOnJS from react-native-reanimated.

What's not possible?

  1. At the moment, only iOS is implemented. I cannot implement Android until react-native-reanimated gets published with source-code (no prebuilt .aar)
  2. Since the library uses JSI for synchronous native methods access, remote debugging (e.g. with Chrome) is no longer possible. Instead, you should use Flipper.
  3. All functions you are calling inside a custom thread, must be workletized to truly run on a separate thread. So add the 'worklet' directive at the top of every function you're calling in that thread (including the thread callback itself), and don't forget to install the Reanimated babel plugin.

License

MIT

Credits

Note: Technically this is not multithreading, but rather multiprocessing.

You might also like...
lc is a fast multi-threaded line counter.
lc is a fast multi-threaded line counter.

Fast multi-threaded line counter in Modern C++ (2-10x faster than `wc -l` for large files)

Termite-jobs - Fast, multiplatform fiber based job dispatcher based on Naughty Dogs' GDC2015 talk.

NOTE This library is obsolete and may contain bugs. For maintained version checkout sx library. until I rip it from there and make a proper single-hea

Sqrt OS is a simulation of an OS scheduler and memory manager using different scheduling algorithms including Highest Priority First (non-preemptive), Shortest Remaining Time Next, and Round Robin
Sqrt OS is a simulation of an OS scheduler and memory manager using different scheduling algorithms including Highest Priority First (non-preemptive), Shortest Remaining Time Next, and Round Robin

A CPU scheduler determines an order for the execution of its scheduled processes; it decides which process will run according to a certain data structure that keeps track of the processes in the system and their status.

A novel technique to communicate between threads using the standard ETHREAD structure
A novel technique to communicate between threads using the standard ETHREAD structure

🕵️ dearg-thread-ipc-stealth Usage There are two main exported methods, one to read from another thread, and another to serve the content to another t

Exploration of x86-64 ISA using speculative execution.

Haruspex /həˈrʌspeks/ A religious official in ancient Rome who predicted the future or interpreted the meaning of events by examining the insides of b

Discrete-event simulation in C++20 using coroutines

SimCpp20 SimCpp20 is a discrete-event simulation framework for C++20. It is similar to SimPy and aims to be easy to set up and use. Processes are defi

Thread pool - Thread pool using std::* primitives from C++17, with optional priority queue/greenthreading for POSIX.

thread_pool Thread pool using std::* primitives from C++11. Also includes a class for a priority thread pool. Requires concepts and C++17, including c

Thread-pool - Thread pool implementation using c++11 threads
Thread-pool - Thread pool implementation using c++11 threads

Table of Contents Introduction Build instructions Thread pool Queue Submit function Thread worker Usage example Use case#1 Use case#2 Use case#3 Futur

Parallel implementation of Dijkstra's shortest path algorithm using MPI

Parallel implementation of Dijkstra's shortest path algorithm using MPI

Comments
  • Android support (with `Android.mk`)

    Android support (with `Android.mk`)

    opened by mrousavy 1
  • Try support android

    Try support android

    The entire source code is written in C++, so I don't really have to do anything except finding the right CMakeLists configuration. That's going to be hard though, since I've never really used CMake before. Any help appreciated!

    Mission

    The user has react-native-reanimated installed via npm which lives on his machine as an .aar. react-native-multithreading is also an .aar. How do I "dynamically" include reanimated aar in my aar without copying the entire REA source code into my lib?

    opened by mrousavy 0
  • Added a bunch of new stuff

    Added a bunch of new stuff

    Hey! I know you haven't been working on this actively but I thought of takings some time to up a few things. Here's the list:

    1. Updated the Scheduler similar to react-native-vision-camera so now it creates it's own Scheduler.
    2. Added support for loading JS modules! Basically you can drop a module file in app assets folder & it will be loaded into the worker thread. For example loading a html parser or any other such library for doing expensive work on the worker & returning the result.
    3. Updated the library to support latest react native version
    4. Added the ability to register native JSI plugins with the worker. This can be further expanded to enable access to all react native modules through a custom bridge implementation.
    5. Added eval support.
    6. Lazily install JSI bindings with install method.
    opened by ammarahm-ed 1
  • docs(SETUP.md): correct other JSI libs example

    docs(SETUP.md): correct other JSI libs example

    • [x] Correct the import path for the JSI module in the example
    • [x] ~~Add MMKV into the example - I feel most people would be using these together and could use the example.~~

    Also, I had to follow this suggested fix but replace mmkv with multithreading.

    opened by david-gettins 2
Releases(v1.1.1)
Owner
Marc Rousavy
they call me ranch cause I be dressing
Marc Rousavy
A multithreading library implemented in C

CthreAd A multi-threading library for C Programs Report Bug · Request Feature Table of Contents About The Project One-One Many-One Usage Testing Contr

Chetas Borse 6 May 6, 2021
C++React: A reactive programming library for C++11.

C++React is reactive programming library for C++14. It enables the declarative definition of data dependencies between state and event flows. Based on

Sebastian 968 Dec 22, 2022
An easy to use C++ Thread Pool

mvThreadPool (This library is available under a free and permissive license) mvThreadPool is a simple to use header only C++ threadpool based on work

Jonathan Hoffstadt 30 Dec 8, 2022
Simple and fast C library implementing a thread-safe API to manage hash-tables, linked lists, lock-free ring buffers and queues

libhl C library implementing a set of APIs to efficiently manage some basic data structures such as : hashtables, linked lists, queues, trees, ringbuf

Andrea Guzzo 392 Dec 3, 2022
Parallel-hashmap - A family of header-only, very fast and memory-friendly hashmap and btree containers.

The Parallel Hashmap Overview This repository aims to provide a set of excellent hash map implementations, as well as a btree alternative to std::map

Gregory Popovitch 1.7k Jan 3, 2023
Bistro: A fast, flexible toolkit for scheduling and running distributed tasks

Bistro is a flexible distributed scheduler, a high-performance framework supporting multiple paradigms while retaining ease of configuration, management, and monitoring.

Facebook 1k Dec 19, 2022
A fast multi-producer, multi-consumer lock-free concurrent queue for C++11

moodycamel::ConcurrentQueue An industrial-strength lock-free queue for C++. Note: If all you need is a single-producer, single-consumer queue, I have

Cameron 7.4k Jan 3, 2023
A fast single-producer, single-consumer lock-free queue for C++

A single-producer, single-consumer lock-free queue for C++ This mini-repository has my very own implementation of a lock-free queue (that I designed f

Cameron 2.9k Jan 5, 2023
Fast, generalized, implementation of the Chase-Lev lock-free work-stealing deque for C++17

riften::Deque A bleeding-edge lock-free, single-producer multi-consumer, Chase-Lev work stealing deque as presented in the paper "Dynamic Circular Wor

Conor Williams 120 Dec 22, 2022
Light, fast, threadpool for C++20

riften::Thiefpool A blazing-fast, lightweight, work-stealing thread-pool for C++20. Built on the lock-free concurrent riften::Deque. Usage #include "r

Conor Williams 67 Dec 28, 2022