question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Pseudo memory leak after removing many Views from screen (ios)

See original GitHub issue

Environment

  React Native Environment Info:
    System:
      OS: macOS High Sierra 10.13.6
      CPU: x64 Intel(R) Core(TM) i5-6360U CPU @ 2.00GHz
      Memory: 84.61 MB / 8.00 GB
      Shell: 3.2.57 - /bin/bash
    Binaries:
      Node: 9.11.2 - ~/.nvm/versions/node/v9.11.2/bin/node
      Yarn: 1.5.1 - /usr/local/bin/yarn
      npm: 5.6.0 - ~/.nvm/versions/node/v9.11.2/bin/npm
      Watchman: 4.7.0 - /usr/local/bin/watchman
    SDKs:
      iOS SDK:
        Platforms: iOS 12.0, macOS 10.14, tvOS 12.0, watchOS 5.0
      Android SDK:
        Build Tools: 23.0.1, 23.0.3, 24.0.0, 24.0.1, 25.0.0, 25.0.1, 25.0.2, 25.0.3, 26.0.1, 26.0.2, 27.0.0, 27.0.3
        API Levels: 23, 24, 25, 26, 27
    IDEs:
      Android Studio: 3.1 AI-173.4670197
      Xcode: 10.0/10A255 - /usr/bin/xcodebuild
    npmPackages:
      react: 16.5.0 => 16.5.0 
      react-native: 0.57.1 => 0.57.1 
    npmGlobalPackages:
      create-react-native-app: 2.0.2

Description

Disclaimer: Yet not totally sure if the behavior is an issue, but as it’s causing a somewhat large amount of crashes in my app I’m considering it to be a bug.

The issue is that after performing operations expected to have no impact in memory consumption the total memory usage is higher then the previous baseline. Trying to isolate the cause I ended up with a fairly simple app (shown below) that adds and removes views from the screen and have this pseudo memory leak.

XCode tools to track memory indicate that: (all tests made in production scheme)

1. Adding some views and then removing them memory consumption increases screen shot 2018-09-29 at 10 25 17

2. Add and remove the same amount of views again doesn’t increase the memory consumption, but if a larger number of views are added some more memory leak screen shot 2018-09-29 at 10 56 05

Note that the second peak in the graph is lower than the first. Also, from time to time, some of the retained memory is freed (not in the graph), but I couldn’t grasp the possible trigger. Considering this pattern I’m inclined to think this is some kind of cache and not a leak, but I couldn’t find anything about it.

In my production app a similar pattern can be repeated until the device runs out of memory. This was tested in iPhone5, but there are similar reports on Crashlytics for other devices.

I was worried that this could be a simple to answer question, so I tried StackOverflow without success so far.

Reproducible Demo

The issue is reproducible by react-native init and changing the App.js to be

import React from 'react';                                                                                                                                                                             
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';                                                                                                                               

export default class App extends React.Component {                                                                                                                                                     
  constructor(props) {                                                                                                                                                                                 
    super(props);                                                                                                                                                                                      
    this.state = {                                                                                                                                                                                     
      count: 0,                                                                                                                                                                                        
    };                                                                                                                                                                                                 
  }                                                                                                                                                                                                    

  render() {                                                                                                                                                                                           
    const { count } = this.state;                                                                                                                                                                      
    const extraContent = new Array(200 * count).fill().map((_, index) => (                                                                                                                             
      <View key={index}><Text>Line {index}</Text></View>                                                                                                                                               
    ));                                                                                                                                                                                                

    return (                                                                                                                                                                                           
      <View style={styles.container}>                                                                                                                                                                  
        <View style={styles.actions}>                                                                                                                                                                  
          <TouchableOpacity onPress={() => this.setState({ count: count + 1})}>                                                                                                                        
            <View style={styles.button}>                                                                                                                                                               
              <Text style={styles.buttonText}>Add</Text>                                                                                                                                               
            </View>                                                                                                                                                                                    
          </TouchableOpacity>                                                                                                                                                                          
          <TouchableOpacity onPress={() => count > 0 && this.setState({ count: count - 1})}>                                                                                                           
            <View style={styles.button}>                                                                                                                                                         
              <Text style={styles.buttonText}>Remove</Text>                                                                                                                                            
            </View>                                                                                                                                                                                    
          </TouchableOpacity>                                                                                                                                                                          
        </View>                                                                                                                                                                                        
        <View>                                                                                                                                                                                         
          <Text>Current count: {count}</Text>                                                                                                                                                          
          <View>{extraContent}</View>                                                                                                                                                                  
        </View>                                                                                                                                                                                        
      </View>                                                                                                                                                                                          
    );                                                                                                                                                                                                 
  }                                                                                                                                                                                                    
}                                                                                                                                                                                                      

const styles = StyleSheet.create({                                                                                                                                                                     
  container: {                                                                                                                                                                                         
    flex: 1,                                                                                                                                                                                           
    marginTop: 50,                                                                                                                                                                                     
    width: '100%',                                                                                                                                                                                     
  },                                                                                                                                                                                                   
  actions: {                                                                                                                                                                                           
    flexDirection: 'row',                                                                                                                                                                              
    alignItems: 'center',                                                                                                                                                                              
    justifyContent: 'space-around',                                                                                                                                                                    
  },                                                                                                                                                                                                   
  buttonText: {                                                                                                                                                                                        
    color: '#ffffff',                                                                                                                                                                                  
  },                                                                                                                                                                                                   
  button: {                                                                                                                                                                                            
    alignItems: 'center',                                                                                                                                                                              
    justifyContent: 'center',                                                                                                                                                                          
    backgroundColor: '#95afe5',                                                                                                                                                                        
    height: 50,                                                                                                                                                                                        
    width: 100,                                                                                                                                                                                        
    marginBottom: 5,                                                                                                                                                                                   
    borderRadius: 5,                                                                                                                                                                                   
  },                                                                                                                                                                                                   
});

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:14
  • Comments:10

github_iconTop GitHub Comments

7reactions
kelsetcommented, Oct 8, 2018

Hey @leonardocarvalho thank you so much for the detailed investigation, I’ll show this to the Core since it’s a pretty important issue IMHO.

4reactions
kelsetcommented, Oct 22, 2018

Hey Leonardo, thanks for the ping - sadly noone was able to check it last time I linked it, I’ll try again next week since this week there is ReactConf and the JSI is landing too, so a lot is moving.

Read more comments on GitHub >

github_iconTop Results From Across the Web

React Native pseudo leaking memory after remove elements ...
The code adds and removes some views from the screen when you press and or remove. It's expected that pressing Add three times...
Read more >
Tracking down a memory leak | Apple Developer Forums
I've discovered that my app has a memory leak, where when I close a window, it disappears from the screen but it (along...
Read more >
Memory leak - Wikipedia
In computer science, a memory leak is a type of resource leak that occurs when a computer program incorrectly manages memory allocations in...
Read more >
Everything you need to know about Memory Leaks in iOS
A memory leak occurs when a given memory space cannot be recovered by the ARC (Automatic Reference Count) because it is unable to...
Read more >
Memory leak in C++ and How to avoid it? - GeeksforGeeks
Memory leakage occurs in C++ when programmers allocates memory by using new keyword and forgets to deallocate the memory by using delete() ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found