简体   繁体   English

Redux + ImmutableJS - 如何垃圾收集太大的商店?

[英]Redux + ImmutableJS - how to garbage collect too large store?

I'm using Redux with ImmutableJS. 我正在使用Redux和ImmutableJS。 In my SPA (quite complicated administration system), users often load a lot of data into stores (thousands rows for many tables). 在我的SPA(非常复杂的管理系统)中,用户经常将大量数据加载到存储中(许多表的数千行)。 After opening several pages and having too many data in the store, the app becomes significantly slower, because the ImmutableJS store can contain even millions entries. 打开多个页面并在商店中存储过多数据后,应用程序变得非常慢,因为ImmutableJS商店甚至可以包含数百万个条目。

How can I "delete" something from the store, so that the data don't slow down the app? 如何从商店“删除”某些内容,以便数据不会减慢应用程序的速度? I know that this would be against its main principle, but how else would you solve it? 我知道这将违背其主要原则,但你怎么解决呢?

Using a common website with for example jQuery, it would be pretty easy. 使用具有例如jQuery的通用网站,这将非常简单。 With every page refresh, everything unnecessary would be garbage collected. 每次刷新页面时,所有不必要的内容都会被垃圾回收。 Therefore, 2-3 thousands entries for one page would be ok, but when opening a new page, the reducer loads new data, but the old ones are still being referenced to. 因此,一个页面的2-3,000个条目就可以了,但是当打开一个新页面时,reducer会加载新数据,但旧的数据仍然被引用。

And I don't want to force the user to reload the page, of course. 当然,我不想强​​迫用户重新加载页面。

Triple-Check this is really memory bloat and not just unnecessary re-rendering/re-computation 三重检查这确实是内存膨胀,而不仅仅是不必要的重新渲染/重新计算

Mutating state in Redux is almost always a really bad idea as it's a sort of prerequisite for the library. Redux中的变异状态几乎总是一个非常糟糕的主意,因为它是库的一种先决条件。 My first concern would be to triple-check that you are indeed running into memory issues due to memory bloat and not due to unnecessary re-renders or due to unnecessary computations. 我的第一个问题是三重检查你是否因为内存膨胀而导致内存问题,而不是由于不必要的重新渲染或由于不必要的计算。 By this I mean, if you are keeping huge amounts of data in the same place, make sure you are not doing something that causes React to unnecessarily re-render things or sift through too much data. 我的意思是,如果你在同一个地方保存大量数据,请确保你没有做任何导致React不必要地重新渲染事物或筛选过多数据的东西。

You can solve that issue by judicial use of the reselect library or by using some other type of memoization that will retrieve data from your reducers in a manner that avoids unnecessary recomputation. 您可以通过司法使用重新选择库或使用其他类型的记忆来解决该问题,这些记忆将以避免不必要的重新计算的方式从您的Reducer中检索数据。 Similarly, make sure you aren't unnecessarily re-rendering every item in your entire list just when changing a single row. 同样,确保在更改单行时不会不必要地重新渲染整个列表中的每个项目

Get rid of references to previous state 摆脱对以前状态的引用

To get something to be garbage compiled in JavaScript, you just make sure that nothing is referencing it any longer . 要在JavaScript中编译垃圾,您只需确保不再引用任何内容

If you really need to go down this path, it's essential that you don't keep the old page's data "alive" if you will because JavaScript only garbage collects things that are no longer referenced. 如果你真的需要沿着这条路走下去,那么你必须保持旧页面的数据“活着”,因为只有JavaScript才会收集不再引用的东西。

Vanilla Redux is not holding on to previous states under the hood. Vanilla Redux并没有坚持以前的状态。 All it's doing is keeping the current state in a let variable and then changing its value after getting the new state from dispatching the action to the root reducer (see source code ). 它正在做的就是将当前状态保持在let变量中,然后在从调度操作到root reducer获取新状态后更改其值(请参阅源代码 )。

So, I would ensure I''m not using something like redux dev tools which persists previous state . 所以,我会确保我没有使用像之前持续存在状态的 redux dev工具。

Then in the reducer, create a new object that doesn't use the previous data in any way, but rather returns a new object with the new data: 然后在reducer中,创建一个不以任何方式使用以前数据的新对象,而是返回一个包含新数据的新对象:

const data = (state, action) => {
  switch (action.type) {
    case 'RETRIEVE_DATA_SUCCESS':
      return action.payload;
    default:
      return state
  }
}

I suggest reading up on Chrome's memory profiling tools here to make sure this is working correctly. 我建议在这里阅读Chrome的内存分析工具以确保它正常工作。

I would suggest instead of keeping the whole data in the store to keep a pointer of it to a memory solution (localstorage,REDIS etc). 我建议不要将整个数据保存在商店中,以便将其指向内存解决方案(localstorage,REDIS等)。 I would have use PouncDB and store the _rev revision number only in my store. 我会使用PouncDB并仅在我的商店中存储_rev修订号。

The previous post is wrong about Immutablejs keeping old data 'alive'...well, in the sense it's being described. 关于Immutablejs保持旧数据“活着”的上一篇文章是错误的......好吧,从某种意义上说它正在被描述。 Immutablejs uses structural sharing, which just means that it will only create a new node and it's children, while sharing the rest of the trie with the old data. Immutablejs使用结构共享,这意味着它只会创建一个新节点和它的子节点,同时与旧数据共享其余的trie。 If you look at the image below, you'll see that the green and yellow dots on the right are new the data sharing its structure with the old data. 如果您查看下面的图像,您会看到右边的绿色和黄色点是新数据,它与旧数据共享其结构。

The old data sections (the right hand blue dots) are available for garbage collection, so long as you don't keep keep a reference to it somewhere else in your app . 旧数据部分(右手蓝点) 可用于垃圾收集,只要您不在应用程序的其他位置继续引用它 Keeping a reference is mostly beneficial if you'd like to add a time traveling feature to your app. 如果您想在应用中添加时间旅行功能,那么保持参考最有用。

Had you deep cloned each object per idiomatic Redux, then you'd have an even bigger memory problem without immutablejs' structural sharing. 如果您根据惯用的Redux深入克隆每个对象,那么在没有immutablejs的结构共享的情况下,您会遇到更大的内存问题。 So without seeing some code, I doubt immutable is the issue here. 所以没有看到一些代码,我怀疑这里的问题是不可改变的。

Are you by chance using toJS() ? 你是不是偶然使用toJS() If you are, that is an expensive operation and should be avoided unless absolutely necessary. 如果你是,这是一项昂贵的操作,除非绝对必要,否则应该避免。 It also disconnects the immutable instance and you'll lose all the benefits of structural sharing. 它还会断开不可变实例的连接,您将失去结构共享的所有好处。 This is a common mistake I've seen. 这是我见过的一个常见错误。 You can get access to the values without calling toJS() like so 您可以访问值而无需像这样调用toJS()

const immVal = List([1,2,3]) console.log([...immVal.values()])

Lee Byron's talk (creator of immutablejs) structual sharing @23:40 and garbage collection @24:50 Lee Byron的演讲(immutablejs的创造者)结构分享@ 23:40和垃圾收集@ 24:50

在此输入图像描述

由于我看到有人推荐PouchDB,我希望您对reduxdb进行试用,我们已经在生产中使用了近一年,并且没有发现任何性能问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM