react-native-reanimated icon indicating copy to clipboard operation
react-native-reanimated copied to clipboard

Extract worklet logic from value unpacker

Open tomekzaw opened this issue 1 year ago • 5 comments

Summary

This PR moves the logic behind creation of worklets from JS valueUnpacker directly into C++ ShareableWorklet::toJSValue.

It's a step towards removing valueUnpacker which has been causing some problems recently (see #5660).

Fixes #5445.

Test plan

App.tsx
import { StyleSheet, View, Button } from 'react-native';

import { runOnUI } from 'react-native-reanimated';
import React from 'react';

export default function EmptyExample() {
  const handlePress = () => {
    runOnUI(() => {
      console.log('Hello world!');
    })();
  };

  return (
    <View style={styles.container}>
      <Button title="ShareableWorklet" onPress={handlePress} />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
});

tomekzaw avatar Feb 19 '24 20:02 tomekzaw

Some performance measurements:

main debug 136360 us main release 86487 us

this PR debug 397071 us this PR release 242305 us

😢

tomekzaw avatar Apr 02 '24 16:04 tomekzaw

Haven't had the time to check it yet, but did you verify that the caches are actually utilized? Maybe that's the reason for performance issues.

tjzel avatar Apr 02 '24 16:04 tjzel

@tjzel You are right, it looks like after the changes the cache does not work as expected.

Before:

worklet hash: creation time
17031627990684: 109 us
17031627990684: 5 us
17031627990684: 3 us
17031627990684: 3 us
17031627990684: 3 us
17031627990684: 3 us
17031627990684: 3 us
17031627990684: 3 us

After:

worklet hash: creation time
17031627990684: 123 us
17031627990684: 110 us
17031627990684: 110 us
17031627990684: 108 us
17031627990684: 107 us
17031627990684: 107 us
17031627990684: 113 us
17031627990684: 106 us

tomekzaw avatar Apr 03 '24 06:04 tomekzaw

CWCT (cumulative worklet creation time)

#include <iostream>
#include <sstream>
#include <chrono>

using namespace std::chrono;

auto start = high_resolution_clock::now();
// ShareableWorklet::toJSValue
auto end = high_resolution_clock::now();
auto duration = duration_cast<microseconds>(end - start);
static unsigned long acc = 0;
acc += duration.count();
std::cout << static_cast<unsigned long long>(workletHash.asNumber()) << ": " << acc << " us" << std::endl;
main this PR
debug 122455 us 122862 us
release 82094 us 82824 us

So it's just a 1% slower 🥳

tomekzaw avatar Apr 04 '24 20:04 tomekzaw

WIT (worklet invocation time)

function worklet() {
  'worklet';
  // do nothing
}
runOnUI(() => {
  const start = performance.now();
  for (let i = 0; i < 10000000; i++) {
    worklet();
  }
  const end = performance.now();
  console.log(end - start, 'ms');
})();
main this PR
debug 373 ms 371 ms
release 347 ms 347 ms

tomekzaw avatar Apr 04 '24 20:04 tomekzaw