-
Notifications
You must be signed in to change notification settings - Fork 476
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
[iOS] Image re-rendering with potential memory leak #2909
Labels
bug
Something isn't working
Comments
Currently we are not using setExternalMemory pressure from Hermes and
therefore this skiaImage gets garbage collected eventually but at a
much later time than expected.
calling skiaImage.dispose() when setting a new image should help.
I would be curious to see the behavior you are experiencing. In my
case we can log that all objects are properly deleted from the garbage
collector but I still see a very high memory pressure, not sure why. I
asked the questions on the hermes github:
facebook/hermes#1518
…On Thu, Jan 23, 2025 at 3:22 PM Dimuthu Wannipurage ***@***.***> wrote:
Description
I am trying to build a pdf document viewer using react native skia and reanimated. This requires rendering bitmap tiles of a pdf page at different resolution levels when we peform pinch zoom on canvas. As a result of that, I have to regenerat the Skia Image multiple times and assign to the same image component. Please have a look at following simplified code sample. The issue I am struggling is, when I zoom in and generate images of 3000 x 3000 pixels, memory usage goes up as expected but when I zoom out and generate 300x300 bitmaps, memory does not go back down. I initially though that this is related to delayed garbage collection but it seems like not the case as the memory is occupied permanantly for a long period of time. I lookd at the memory profile and there is a lot of objects with stuck at SkData::MakeWithCopy and I think those are the images I created on demad when the pinch zoom ended. Can you help me to figure out why this memory leak is happening and what could be the potential resolution for this?
import React, { useEffect, useState } from 'react';
import { View, StyleSheet } from 'react-native';
import { Canvas, Skia, AlphaType, ColorType, Fill, Image, SkImage } from ***@***.***/react-native-skia';
import { GestureDetector, Gesture, GestureHandlerRootView } from 'react-native-gesture-handler';
import Animated, {
useSharedValue,
useDerivedValue,
runOnJS,
} from 'react-native-reanimated';
function App(): React.JSX.Element {
const tileSize = 512;
const scale = useSharedValue(1);
const translationX = useSharedValue(0);
const translationY = useSharedValue(0);
const [scaleEnd, setScaleEnd] = useState(1);
const [skiaImage, setSkiaImage] = useState<SkImage>();
const createTile = (tileSize: number) => {
const pixels = new Uint8Array(tileSize * tileSize * 4);
pixels.fill(255);
let i = 0;
for (let x = 0; x < tileSize; x++) {
for (let y = 0; y < tileSize; y++) {
pixels[i++] = (x * y) % 255;
}
}
const data = Skia.Data.fromBytes(pixels);
const img = Skia.Image.MakeImage(
{
width: tileSize,
height: tileSize,
alphaType: AlphaType.Opaque,
colorType: ColorType.RGBA_8888,
},
data,
tileSize * 4
);
return img;
}
if (skiaImage === null) {
return <View style={styles.container} />;
}
const panGesture = Gesture.Pan().onChange((e) => {
translationX.value += e.changeX;
translationY.value += e.changeY;
});
const scaleGesture = Gesture.Pinch().onChange((e) => {
scale.value += e.scaleChange - 1;
}).onEnd(() => {
runOnJS(() => {
setScaleEnd(scale.value);
})();
}).runOnJS(true);
useEffect(() => {
const skImg = createTile(tileSize * scale.value);
console.log("Skia image calculating for tile size " + tileSize * scale.value);
if (skImg !== null) {
setSkiaImage(skImg);
}
}, [scaleEnd]);
return (
<GestureHandlerRootView>
<View style={{ flex: 1 }}>
<Canvas style={{ flex: 1 }}>
<Fill color="pink" />
<Image image={skiaImage} x={translationX} y={translationY} width={useDerivedValue(() => tileSize * scale.value)} height={useDerivedValue(() => tileSize * scale.value)} />
</Canvas>
<GestureDetector gesture={Gesture.Race(panGesture, scaleGesture)}>
<Animated.View style={StyleSheet.absoluteFill} />
</GestureDetector>
</View>
</GestureHandlerRootView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "pink",
},
canvasContainer: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
canvas: {
flex: 1,
},
animatedCanvas: {
flex: 1,
},
});
export default App;
React Native Skia Version
1.9.0
React Native Version
0.76.5
Using New Architecture
Enabled
Steps to Reproduce
Run the attached code and try multiple pinch zoom on iOS
Snack, Code Example, Screenshot, or Link to Repository
Screenshot.2025-01-23.at.9.04.32.AM.png (view on web) Screenshot.2025-01-23.at.9.18.32.AM.png (view on web)
—
Reply to this email directly, view it on GitHub or unsubscribe.
You are receiving this email because you are subscribed to this thread.
Triage notifications on the go with GitHub Mobile for iOS or Android.
|
@wcandillon I tried to dispose the old image but that raised some EXEC_BAD_ACCESS errors on C++. Please let me whether following way is correct?
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Description
I am trying to build a pdf document viewer using react native skia and reanimated. This requires rendering bitmap tiles of a pdf page at different resolution levels when we peform pinch zoom on canvas. As a result of that, I have to regenerat the Skia Image multiple times and assign to the same image component. Please have a look at following simplified code sample. The issue I am struggling is, when I zoom in and generate images of 3000 x 3000 pixels, memory usage goes up as expected but when I zoom out and generate 300x300 bitmaps, memory does not go back down. I initially though that this is related to delayed garbage collection but it seems like not the case as the memory is occupied permanantly for a long period of time. I lookd at the memory profile and there is a lot of objects with stuck at SkData::MakeWithCopy and I think those are the images I created on demad when the pinch zoom ended. Can you help me to figure out why this memory leak is happening and what could be the potential resolution for this?
React Native Skia Version
1.9.0
React Native Version
0.76.5
Using New Architecture
Steps to Reproduce
Run the attached code and try multiple pinch zoom on iOS
Snack, Code Example, Screenshot, or Link to Repository
The text was updated successfully, but these errors were encountered: