Extract worklet logic from value unpacker
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',
},
});
Some performance measurements:
main debug 136360 us main release 86487 us
this PR debug 397071 us this PR release 242305 us
😢
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 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
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 🥳
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 |