rt2zz / redux-persist

persist and rehydrate a redux store
MIT License
12.97k stars 866 forks source link

Takes time to persist the store in AsyncStorage #720

Open alexmngn opened 6 years ago

alexmngn commented 6 years ago

I use redux-persist on a React-Native app. I noticed it takes about 20 seconds before my store gets stored in the AsyncStorage. If I restart my app in less than that, the REHYDRATE restores the old version of the store. I'm wondering why is this so long? Is there a delay? Can it be customized? AsyncStorage is pretty fast on its own. Thanks

rt2zz commented 6 years ago

This should not be the case. The delay should be something like a few ms.

How many reducers do you have? Also have you set a throttle value in the persistReducer config?

alexmngn commented 6 years ago

I've only persisted a single reducer using persistReducer as I only need to cache a single reducer. I don't have any throttle value. My store isn't very big and looks like this:

  const appReducer = combineReducers({
    reducer1: myReducer1,
    reducer2: myReducer2,
    reducer3: persistReducer(
      { storage, key: 'reducer3', transforms: [persistFilter] },
      myReducer3,
    ),
    reducer4: myReducer4,
  });

  const store = createStore(appReducer, compose(...enhancers));
  const persistor = persistStore(store);

In the enhancers I mostly have dev tools and saga middleware.

stanislav-grin commented 6 years ago

@alexmngn did you resolve this issue? I have the same problem. It takes ~10s before redux-persist stored in the storage. I have throttle set to 1000ms, but I noticed that if I reduce this value, redux-persist writes data much faster, but I don't want to have such small throttle value due to performance issues.

Dante-101 commented 6 years ago

I found throttle's implementation to be different from what the documentation states. Throttle actually slows down the processing of modified keys in the state rather than throttling the write.

I found this code in createPersistoid.js - setInterval(processNextKey, throttle). processNextKey only processes the key and stages the values for writing. The write happens when there are no more keys to be processed. So the throttle technically delays state persistence by throttle * numModifiedKeys ms.

So if you have large throttle value and if the state keeps updating, I believe it may even lead to starvation. For the current implementation, I suggest keeping throttle to a really low value like 5 or 10 ms.

@rt2zz How about having a synchronous function to process the modified keys, and then trigger the write to the storage. We should throttle this function. Ideally, it should be a mix of throttle and debounce. Keep calling this function once every X ms (throttle) on state update and if there are any modified keys since the last persist and more than some Y ms (debounce) has passed, call the function again. The idea is similar to lodash.throttle with leading and trailing set to true.

alexey-m-ukolov commented 6 years ago

I also have this issue. I'm not setting throttle in the config, so redux-persist uses default value of 0. On my emulator I consistently see a 3 seconds delay between update and processNextKey + stagedWrite. On real devices in production build delay is also present, but it's hard to quantify it. selection_026

I have about a dozen persisted reducers with not much data that gets saved to storage, so I don't think it's because of some heavy load.

I don't see where this delay may come from in the redux-persist code though. Maybe it's more related to how setInterval works in react-native itself? I've tried setting throttle to 10 ms (maybe setInterval and 0 delay in react-native don't play nice with each other), but nothing changed.

ozzyogkush commented 6 years ago

Just a note but I do not believe this is limited to AsyncStorage. Trying to use a throttle of any value on a regular web app with localStorage causes updated state to be ignored in persistence, even after manually calling persistor.flush().

Dante-101 commented 6 years ago

@ozzyogkush: There are few bugs around persistence. I found two and fixed them but this project is running late with merging pull requests. See https://github.com/rt2zz/redux-persist/issues/811.

peteroid commented 6 years ago

Just a friendly reminder that I realized that the state hasn't changed as I was doing something like:

ACTION: {
  const { someObject } = state
  someObject.key = 'updated'
  return {
    someObject
  }
}

As the persistReducer would only do a shallow compare, the above case would be missed out for persistence. I was too stupid to spend many days thinking this is the problem with the library. But yeah, double check the code.

bvanderhoof commented 4 years ago

I recently updated to 6.0 and noticed that the initial persistence is really slow (6 seconds). Did anyone find a solution? Seems throttle is not working as expected?

bvanderhoof commented 4 years ago

I solved my scenario here https://github.com/rt2zz/redux-persist/issues/786