React-Native + Redux + ImmutableJS内存泄漏

时间:2018-02-02 00:48:13

标签: ios react-native memory-leaks redux immutable.js

我的React-Native应用程序中有一个奇怪的内存泄漏。这是一个持续的RAM增长。 我的状态被规范化,然后转换为不可变状态。有一个套接字处理程序可以更新状态中的现有对象。这会导致RAM在新消息更新状态时缓慢增加。

国家

const state = {
    entities: {
        2000: {
            1: {
                id: 1,
                name: "I am normalized",
                coordinates:[
                    {
                        lat: 0,
                        lng: 0
                    }
                ]
            },
            2: {
                id: 2,
                name: "me too",
                coordinates:[
                    {
                        lat: 0,
                        lng: 0
                    }
                ]
            }
        },
        1337: {
            2: {
                id: 2,
                name: "me too",
                coordinates:[
                    {
                        lat: 0,
                        lng: 0
                    }
                ]
            },
            3: {
                id: 3,
                name: "also normalized",
                coordinates:[
                    {
                        lat: 0,
                        lng: 0
                    }
                ]
            }
        }
    },
    results: {
        2000: [1,2],
        1337: [2,3]
    },
};

然后将fromJS()转换为不可变状态。

我有一个套接字处理程序,它将action.payload传递给reducer。

action = {
    payload: {
        message_type: COORDINATES_UPDATE,
        messages: [
            {
                id: 1,
                coordinates: [
                    {
                        lat: 180,
                        lng: 180
                    }
                ]
            },
            {
                id: 2,
                coordinates: [
                    {
                        lat: 90,
                        lng: 90
                    }
                ]
            }
        ]
    }
}

处理传入操作的reducer

case SOCKET_MESSAGE: {
    let newState = state;
    if(action.payload.message_type == "COORDINATES_UPDATE") {
        action.payload.messages.map((incoming_message) => {
            let id = incoming_message.id;
            let coordinates = incoming_message.coordinates;
            newState.get("results").map((data, entities_id) => {
                if(data.indexOf(id) > -1) {
                    newState = newState.setIn(["entities", entities_id, "" + id, "coordinates"], fromJS(coordinates));
                }
            })
        })
        return newState;
    }
}

这会在results Map()中搜索现有的id,如果确实存在,则会更新实体对象。据我所知,这个逻辑没有问题,状态正确更新并反映在render()组件中,尽管出于调试目的,我渲染空<View />作为我的整个应用程序,并且只更新状态。

然而,每个setInupdateIn会略微增加RAM,并且随着更新的频率,我会在几分钟内增长到GB。

Steady RAM increase

相关套餐:

"react": "16.0.0",
"react-native": "0.50.3",
"immutable": "^3.8.2",
"normalizr": "^3.2.4",
"redux": "^3.7.2",

3 个答案:

答案 0 :(得分:1)

哦,那是一个巨大的;) 你应该检查两件事:

0)你有多少个套接字连接?你可能有5-10,所有数据都是乘以

1)你使用redux-dev-tool吗?在您的情况下,它可能会占用大量内存,请考虑停用生产/测试

答案 1 :(得分:1)

Normalizr最初是为浏览器开发的。实体的内存消耗问题是众所周知的,然而,实际上它并没有被视为障碍,因为浏览器上的页面生命周期足够短。

Best practices to handle memory consumption of normalized data · Issue #47 · paularmstrong/normalizr

同时,在本机应用程序中,必须正确释放内存。不幸的是,目前没有优雅的图书馆或解决方案。妥协计划:

  • 甲。不要使用Normalizr。自己更新每个实体。
  • B中。自己在实体上实现垃圾收集。

答案 2 :(得分:0)

Memory Stabilized

我最终尝试了这个线程和github的许多不同的解决方案,但最耗时(和悲伤)的解决方案效果最好。拿出ImmutableJS。

用lodash函数替换后,内存稳定。

const newState = state; //just because i don't want to mutate state
let updates = {}; //put my updates here
return _.merge({}, newState, updates); //merge into an empty object
每次状态变异时,

reselect都会期望一个新对象,并且我有一个非常嵌套的状态结构。因此我选择_.merge({}, ...)代替_.assign

Stable after 1000+ seconds

还有一点点增长,但这比以前更好。