redux-persist icon indicating copy to clipboard operation
redux-persist copied to clipboard

Does 'debounce' actually exist? I can't find any documentation anywhere.

Open YCMitch opened this issue 6 years ago • 13 comments

I'm getting some huge performance issues (not entirely redux-persist's fault), but I can see 'createPersistoid' eating huge amounts of CPU in Chrome's performance tools.

Anyways, I hear it's worth trying to use debounce, but I can't see it documented anywhere. It's not on the main page, it's not in the docs, and doesn't seem to exist in PersistConfig either.

Does it... actually exist?

YCMitch avatar Oct 17 '19 06:10 YCMitch

debounce was an option in createPersistor in V4 and earlier and didn't make it into createPersistoid in v5. It appears to have been replaced by throttle.

joshuafarray avatar Nov 15 '19 02:11 joshuafarray

I have not used v4 but throttle does not operate as debounce suggests. I fell quit hard due to that assumption.

my current understanding:

  • throttle DOES limit the processing of reducer keys to a certain interval.
  • throttle DOES NOT postpone persisting to a certain duration of inactivity.

In my case I was using a nested persistReducer which operated on a lengthy array. A throttle of 200ms caused it to take minutes for that reducer to persist

midgethoen avatar Jan 28 '20 14:01 midgethoen

Yeah, I tried it out and then gave up on it. I couldn't work out what it was/wasn't doing, but it seemed like some things would just never get persisted, perhaps 30% of the time.

YCMitch avatar Jan 28 '20 22:01 YCMitch

Slightly off topic but @MitchEff„some things“ sounds really unreliable. I have only started using redux-persist. Would you recommend it then or not?

bitflower avatar Jan 29 '20 07:01 bitflower

Look, I'd say redux-persist is kinda unavoidable for a lot of apps and generally works okay, provided there's not too much going on.

Throttle, on the other hand, seems to be barely documented and just didn't seem to persist things quite a lot. Can't tell why, but removing it solved a lot of woes.

YCMitch avatar Jan 29 '20 08:01 YCMitch

@MitchEff I'll use it myself for a while. Need some experience to be able to judge. Thanks

bitflower avatar Feb 07 '20 16:02 bitflower

@rt2zz Are @midgethoen's assumptions correct? It'd be really handy to do this: "postpone persisting to a certain duration of inactivity."

I can't for the life of me figure out why anyone would need it to do this: "limit the processing of reducer keys to a certain interval"

YCMitch avatar Mar 04 '20 04:03 YCMitch

I ended up implementing the debouncing my self in the store I provide to redux-persist. This worked wonders and I‘m now in control of the debouncing. I persist to file system on iOS and Android via CapacitorJS‘s Filesystem plugin.

bitflower avatar Mar 04 '20 06:03 bitflower

I ended up implementing the debouncing my self in the store I provide to redux-persist

interesting, how did you do this?

midgethoen avatar Mar 04 '20 09:03 midgethoen

I can't for the life of me figure out why anyone would need it to do this

arguably, it's like a poor man's requestIdleCallback allowing the DOM to render during a long persist.. (just guessing)

midgethoen avatar Mar 04 '20 09:03 midgethoen

This is my redux-persist config:

const persistConfig: PersistConfig<CaseOsStoreState> = {
  key: 'root',
  keyPrefix: 'co-app-state-',
  storage: CoFileStorage,
  timeout: 0,
  blacklist: [persistenceReducerName]
};

And the CoFileStorage looks like this: https://gist.github.com/bitflower/e0c78ff03a111a7bbb46da73ce5e50b8

bitflower avatar Mar 04 '20 12:03 bitflower

Ah, I see. That’s smart. Thnx for sharing

midgethoen avatar Mar 04 '20 13:03 midgethoen

Our app (which includes a lot of HTML canvas drawing type stuff) rapidly updates state and sometimes those updates include a lot of nested state and decent sized arrays. redux-persist was trying to persist state on every change to it, and the deep cloning required to handle our blacklist caused very noticeable performance issues.

First I wrote a storage adapter that debounced calls to localStorage.setItem(), before realising that this is not the slow part. The slow part is the deep cloning of state that redux-persist must do to handle blacklisting. Some of the internals of redux-persist needed patching.

Unfortunately, its last release (6.0.0) is no longer build-able due to dependency on a malicious package (flat-stream), now zapped from npm. And the commits past that release are also not build-able, as they are part of an incomplete transition from Flow to TS.

So, I ended up patching the existing release of redux-persist (and redux-deep-persist, which I use for easy nested blacklisting) directly. The actual changes are simple - just adding a new debounce key to PersistConfig and debouncing the update() function, which is created by createPersistoid().

This appears to be working fine. The very rapid updates to state (as the user draws on the canvas) are debounced and the only performance lag noticeable is during the edge case that a user stops interacting with the app and then starts interacting again during the debounced but now active persist operation.

Here is the patch for these two packages. You can use the patch-package npm package to handle applying the patches.

https://gist.github.com/psychedelicious/845efcf64c851d76ab5d4a8bcc0eed74

psychedelicious avatar Nov 12 '22 13:11 psychedelicious