繁体   English   中英

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

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

我正在使用Redux和ImmutableJS。 在我的SPA(非常复杂的管理系统)中,用户经常将大量数据加载到存储中(许多表的数千行)。 打开多个页面并在商店中存储过多数据后,应用程序变得非常慢,因为ImmutableJS商店甚至可以包含数百万个条目。

如何从商店“删除”某些内容,以便数据不会减慢应用程序的速度? 我知道这将违背其主要原则,但你怎么解决呢?

使用具有例如jQuery的通用网站,这将非常简单。 每次刷新页面时,所有不必要的内容都会被垃圾回收。 因此,一个页面的2-3,000个条目就可以了,但是当打开一个新页面时,reducer会加载新数据,但旧的数据仍然被引用。

当然,我不想强​​迫用户重新加载页面。

三重检查这确实是内存膨胀,而不仅仅是不必要的重新渲染/重新计算

Redux中的变异状态几乎总是一个非常糟糕的主意,因为它是库的一种先决条件。 我的第一个问题是三重检查你是否因为内存膨胀而导致内存问题,而不是由于不必要的重新渲染或由于不必要的计算。 我的意思是,如果你在同一个地方保存大量数据,请确保你没有做任何导致React不必要地重新渲染事物或筛选过多数据的东西。

您可以通过司法使用重新选择库或使用其他类型的记忆来解决该问题,这些记忆将以避免不必要的重新计算的方式从您的Reducer中检索数据。 同样,确保在更改单行时不会不必要地重新渲染整个列表中的每个项目

摆脱对以前状态的引用

要在JavaScript中编译垃圾,您只需确保不再引用任何内容

如果你真的需要沿着这条路走下去,那么你必须保持旧页面的数据“活着”,因为只有JavaScript才会收集不再引用的东西。

Vanilla Redux并没有坚持以前的状态。 它正在做的就是将当前状态保持在let变量中,然后在从调度操作到root reducer获取新状态后更改其值(请参阅源代码 )。

所以,我会确保我没有使用像之前持续存在状态的 redux dev工具。

然后在reducer中,创建一个不以任何方式使用以前数据的新对象,而是返回一个包含新数据的新对象:

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

我建议在这里阅读Chrome的内存分析工具以确保它正常工作。

我建议不要将整个数据保存在商店中,以便将其指向内存解决方案(localstorage,REDIS等)。 我会使用PouncDB并仅在我的商店中存储_rev修订号。

关于Immutablejs保持旧数据“活着”的上一篇文章是错误的......好吧,从某种意义上说它正在被描述。 Immutablejs使用结构共享,这意味着它只会创建一个新节点和它的子节点,同时与旧数据共享其余的trie。 如果您查看下面的图像,您会看到右边的绿色和黄色点是新数据,它与旧数据共享其结构。

旧数据部分(右手蓝点) 可用于垃圾收集,只要您不在应用程序的其他位置继续引用它 如果您想在应用中添加时间旅行功能,那么保持参考最有用。

如果您根据惯用的Redux深入克隆每个对象,那么在没有immutablejs的结构共享的情况下,您会遇到更大的内存问题。 所以没有看到一些代码,我怀疑这里的问题是不可改变的。

你是不是偶然使用toJS() 如果你是,这是一项昂贵的操作,除非绝对必要,否则应该避免。 它还会断开不可变实例的连接,您将失去结构共享的所有好处。 这是我见过的一个常见错误。 您可以访问值而无需像这样调用toJS()

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

Lee Byron的演讲(immutablejs的创造者)结构分享@ 23:40和垃圾收集@ 24:50

在此输入图像描述

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

暂无
暂无

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

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