Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slimmed deep proxy #23

Merged
merged 19 commits into from
May 17, 2019
Merged

Slimmed deep proxy #23

merged 19 commits into from
May 17, 2019

Conversation

dai-shi
Copy link
Owner

@dai-shi dai-shi commented May 7, 2019

From: theKashey/proxyequal#17 (comment)

I feel like I'd write a slimmed version of deep proxy.

@dai-shi
Copy link
Owner Author

dai-shi commented May 7, 2019

So, the question is whether there's obvious bugs...

src/utils.js Outdated
if (origObj === nextObj) return false;
if (typeof origObj !== 'object') return true;
if (typeof nextObj !== 'object') return true;
if (!affected.has(origObj)) return false; // is this safe???
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is the most curious. It behaves differently from proxyEqual.

@dai-shi
Copy link
Owner Author

dai-shi commented May 8, 2019

Running benchmark deeptree-nested-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark deeptree-nested-useReduxState:
┌─────────┬──────────────┬──────────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                           │
│         │ (Mount, Avg) │                                                                      │
├─────────┼──────────────┼──────────────────────────────────────────────────────────────────────┤
│ 53.41   │ 145.7, 0.4   │ 60,59,58,59,58,59,57,56,58,57,55,56,50,48,47,48,46,49,45,46,48,45,45 │
└─────────┴──────────────┴──────────────────────────────────────────────────────────────────────┘
Running benchmark deeptree-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark deeptree-useReduxState:
┌─────────┬──────────────┬──────────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                           │
│         │ (Mount, Avg) │                                                                      │
├─────────┼──────────────┼──────────────────────────────────────────────────────────────────────┤
│ 40.21   │ 80.5, 0.6    │ 50,52,53,49,50,49,50,53,54,50,51,50,41,32,31,32,31,32,23,22,24,22,22 │
└─────────┴──────────────┴──────────────────────────────────────────────────────────────────────┘
Running benchmark forms-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark forms-useReduxState:
┌─────────┬──────────────┬─────────────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                              │
│         │ (Mount, Avg) │                                                                         │
├─────────┼──────────────┼─────────────────────────────────────────────────────────────────────────┤
│ 57.21   │ 1037.8, 0.3  │ 56,57,56,57,56,59,55,57,58,57,59,58,57,58,57,58,56,57,58,57,58,56,58,58 │
└─────────┴──────────────┴─────────────────────────────────────────────────────────────────────────┘
Running benchmark stockticker-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark stockticker-useReduxState:
┌─────────┬──────────────┬─────────────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                              │
│         │ (Mount, Avg) │                                                                         │
├─────────┼──────────────┼─────────────────────────────────────────────────────────────────────────┤
│ 58.03   │ 202.9, 0.2   │ 55,59,60,59,60,59,58,59,60,59,60,58,60,59,55,56,57,58,56,58,56,55,54,54 │
└─────────┴──────────────┴─────────────────────────────────────────────────────────────────────────┘
Running benchmark tree-view-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark tree-view-useReduxState:
┌─────────┬──────────────┬──────────────────────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                                       │
│         │ (Mount, Avg) │                                                                                  │
├─────────┼──────────────┼──────────────────────────────────────────────────────────────────────────────────┤
│ 50.70   │ 537.7, 1.3   │ 40,53,47,49,47,50,52,54,53,47,54,47,50,52,51,52,57,54,55,48,52,43,59,53,43,52,52 │
└─────────┴──────────────┴──────────────────────────────────────────────────────────────────────────────────┘
Running benchmark twitter-lite-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark twitter-lite-useReduxState:
┌─────────┬──────────────┬────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                     │
│         │ (Mount, Avg) │                                                                │
├─────────┼──────────────┼────────────────────────────────────────────────────────────────┤
│ 57.75   │ 2.5, 1.6     │ 59,60,59,60,59,60,59,60,59,60,59,60,59,58,56,59,57,56,50,47,47 │
└─────────┴──────────────┴────────────────────────────────────────────────────────────────┘

🚀 🚀 🚀
I hope I'm not misunderstanding anything...

src/utils.js Outdated
if (typeof origObj !== 'object') return true;
if (typeof nextObj !== 'object') return true;
if (!affected.has(origObj)) {
return depth !== 0; // false for root object, but true for others
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if this returns false always, we don't need to care about "rest" operator.

I really need help from @theKashey with this stuff...

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That might be needed in other cases. What if you Object.keys(props)?

Copy link
Owner Author

@dai-shi dai-shi May 9, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, it's Symbol(Symbol.iterator). I'm not sure about other cases, but what I could do is to assume the whole object is affected if accessed by a symbol property. (I hesitate writing my own proxy, when I understand that I don't really understand fully...)


(edit) it was not Symbol.iterator, but ownKeys handler. I don't know why I misunderstood that.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And, it's needed for reference equality checking too.

Could we ignore for the root object? Do people do this?

  const state = useReduxState();
  return useMemo(() => ({ foo: 'foo' }), [state]);

Yeah, maybe?

src/utils.js Outdated
}
const changed = affected.get(origObj)
.some(key => isDeepChanged(origObj[key], nextObj[key], affected, cache, depth + 1));
cache.set(origObj, { nextObj, changed });

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To break cycles you have to set cache(to undefined) before diving deeper.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean cycles in state object tree? I need to understand the problem by writing test code...

src/utils.js Outdated
if (typeof val !== 'object') {
return val;
}
if (!proxyMap[key]) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

proxy map should be external to deepProxy to keep the same req equality between calls, or you will get always unique objects each render.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally! I keep forgetting about the ref equality.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And it is not trivial. In the end, I'd reinvent proxyEqual, which I really don't want to do.

src/utils.js Outdated
if (!used.includes(key)) used.push(key);
}
const val = target[key];
if (typeof val !== 'object') {
Copy link

@theKashey theKashey May 8, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is a few objects (like buitins) which could not be proxied. Plus there are "frozen" objects :(

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. I should somehow detect it and work it around. (Or, maybe just warn developers.)

src/utils.js Outdated
affected.set(target, [key]);
} else {
const used = affected.get(target);
if (!used.includes(key)) used.push(key);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This turns out to be "really" slow when used is big.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you tried Set?

Probably it's time to use some V8-level hacks, like a using different approaches and data structures depending on "size".

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I used Set. 8373b97

src/utils.js Outdated
}
}
const changed = affected.get(origObj)
.some(key => isDeepChanged(origObj[key], nextObj[key], affected, cache, depth + 1));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll propose use for loop here, with early break in case of a change.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some does early break though. Anyway, the for loop is often faster, so I will try when we optimize it (after making sure it works correctly.)

@theKashey
Copy link

Looking great, but I urge you to hold it until comprehensive tests written. It took me a while to fix all bugs in proxyequal logic.

@dai-shi
Copy link
Owner Author

dai-shi commented May 9, 2019

@theKashey Thanks so much for your comments. I will write some tests. Honestly, it's hard for me to tell if they are comprehensive or not.

@dai-shi
Copy link
Owner Author

dai-shi commented May 11, 2019

@theKashey I did what I can do at this point. If you have time, your comments are so appreciated.

@dai-shi
Copy link
Owner Author

dai-shi commented May 11, 2019

Benchmark with useReduxState 69023f9
Running benchmark deeptree-nested-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark deeptree-nested-useReduxState:
┌─────────┬──────────────┬─────────────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                              │
│         │ (Mount, Avg) │                                                                         │
├─────────┼──────────────┼─────────────────────────────────────────────────────────────────────────┤
│ 52.79   │ 124.1, 0.4   │ 58,60,58,59,58,57,55,56,58,54,55,54,47,46,50,46,47,48,50,47,46,45,43,43 │
└─────────┴──────────────┴─────────────────────────────────────────────────────────────────────────┘
Running benchmark deeptree-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark deeptree-useReduxState:
┌─────────┬──────────────┬──────────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                           │
│         │ (Mount, Avg) │                                                                      │
├─────────┼──────────────┼──────────────────────────────────────────────────────────────────────┤
│ 40.26   │ 84.9, 0.6    │ 50,52,54,49,52,48,53,51,52,55,51,42,31,32,31,30,31,30,26,22,21,22,22 │
└─────────┴──────────────┴──────────────────────────────────────────────────────────────────────┘
Running benchmark forms-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark forms-useReduxState:
┌─────────┬──────────────┬────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                     │
│         │ (Mount, Avg) │                                                                │
├─────────┼──────────────┼────────────────────────────────────────────────────────────────┤
│ 56.32   │ 1041.9, 0.3  │ 56,55,57,56,57,56,57,56,58,57,58,57,56,55,57,55,56,54,55,56,56 │
└─────────┴──────────────┴────────────────────────────────────────────────────────────────┘
Running benchmark stockticker-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark stockticker-useReduxState:
┌─────────┬──────────────┬────────────────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                                 │
│         │ (Mount, Avg) │                                                                            │
├─────────┼──────────────┼────────────────────────────────────────────────────────────────────────────┤
│ 56.99   │ 194.1, 0.2   │ 56,59,60,59,60,59,60,59,60,59,58,59,57,59,57,56,57,55,56,55,51,55,53,51,51 │
└─────────┴──────────────┴────────────────────────────────────────────────────────────────────────────┘
Running benchmark tree-view-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark tree-view-useReduxState:
┌─────────┬──────────────┬─────────────────────────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                                          │
│         │ (Mount, Avg) │                                                                                     │
├─────────┼──────────────┼─────────────────────────────────────────────────────────────────────────────────────┤
│ 50.27   │ 530.5, 1.4   │ 42,50,54,45,48,47,50,51,55,54,47,53,48,46,51,53,57,52,56,48,51,45,47,55,52,45,54,54 │
└─────────┴──────────────┴─────────────────────────────────────────────────────────────────────────────────────┘
Running benchmark twitter-lite-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark twitter-lite-useReduxState:
┌─────────┬──────────────┬───────────────────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                                    │
│         │ (Mount, Avg) │                                                                               │
├─────────┼──────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ 54.15   │ 3.6, 2.4     │ 59,60,59,60,59,60,59,60,59,60,59,60,58,59,58,57,56,54,55,50,43,44,40,34,33,33 │
└─────────┴──────────────┴───────────────────────────────────────────────────────────────────────────────┘

package.json Outdated
@@ -1,7 +1,7 @@
{
"name": "reactive-react-redux",
"description": "React Redux binding with React Hooks and Proxy",
"version": "2.0.1",
"version": "3.0.0-alpha.0",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

@dai-shi
Copy link
Owner Author

dai-shi commented May 12, 2019

Benchmark with useReduxState 8373b97
Running benchmark deeptree-nested-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark deeptree-nested-useReduxState:
┌─────────┬──────────────┬─────────────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                              │
│         │ (Mount, Avg) │                                                                         │
├─────────┼──────────────┼─────────────────────────────────────────────────────────────────────────┤
│ 53.00   │ 148.8, 0.4   │ 59,58,57,58,59,58,55,56,55,54,57,56,49,47,48,50,48,47,48,45,43,44,45,45 │
└─────────┴──────────────┴─────────────────────────────────────────────────────────────────────────┘
Running benchmark deeptree-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark deeptree-useReduxState:
┌─────────┬──────────────┬────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                     │
│         │ (Mount, Avg) │                                                                │
├─────────┼──────────────┼────────────────────────────────────────────────────────────────┤
│ 39.07   │ 87.1, 0.6    │ 47,49,50,51,48,47,48,52,50,51,50,43,31,30,31,30,27,22,21,22,22 │
└─────────┴──────────────┴────────────────────────────────────────────────────────────────┘
Running benchmark forms-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark forms-useReduxState:
┌─────────┬──────────────┬───────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                            │
│         │ (Mount, Avg) │                                                       │
├─────────┼──────────────┼───────────────────────────────────────────────────────┤
│ 57.14   │ 1049.7, 0.3  │ 55,58,57,58,56,58,56,57,58,60,58,56,57,58,57,58,57,57 │
└─────────┴──────────────┴───────────────────────────────────────────────────────┘
Running benchmark stockticker-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark stockticker-useReduxState:
┌─────────┬──────────────┬───────────────────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                                    │
│         │ (Mount, Avg) │                                                                               │
├─────────┼──────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ 53.85   │ 204.1, 0.2   │ 53,59,60,57,58,59,54,58,56,58,52,55,54,55,54,53,48,52,50,51,50,51,47,49,51,51 │
└─────────┴──────────────┴───────────────────────────────────────────────────────────────────────────────┘
Running benchmark tree-view-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark tree-view-useReduxState:
┌─────────┬──────────────┬─────────────────────────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                                          │
│         │ (Mount, Avg) │                                                                                     │
├─────────┼──────────────┼─────────────────────────────────────────────────────────────────────────────────────┤
│ 50.05   │ 532.5, 1.3   │ 41,50,57,45,51,44,50,53,55,57,46,53,46,47,52,49,56,52,55,53,46,51,41,55,54,44,45,45 │
└─────────┴──────────────┴─────────────────────────────────────────────────────────────────────────────────────┘
Running benchmark twitter-lite-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark twitter-lite-useReduxState:
┌─────────┬──────────────┬────────────────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                                 │
│         │ (Mount, Avg) │                                                                            │
├─────────┼──────────────┼────────────────────────────────────────────────────────────────────────────┤
│ 58.82   │ 2.9, 0.8     │ 59,60,59,60,59,60,59,60,59,60,59,60,59,60,59,58,59,60,56,58,55,59,54,59,59 │
└─────────┴──────────────┴────────────────────────────────────────────────────────────────────────────┘

@dai-shi
Copy link
Owner Author

dai-shi commented May 13, 2019

@theKashey #1 (comment)

If I understand it correctly, it means to use a global proxyCache instead of per-hook proxyCaches.

diff --git a/src/useReduxState.js b/src/useReduxState.js
index 8d01436..888173c 100644
--- a/src/useReduxState.js
+++ b/src/useReduxState.js
@@ -69,12 +69,12 @@ export const useReduxStateRich = () => {
   return trapped.state;
 };
 
+const proxyCache = new WeakMap();
 export const useReduxState = (opts = {}) => {
   const forceUpdate = useForceUpdate();
   const store = useContext(ReduxStoreContext);
   const state = store.getState();
   const affected = new WeakMap();
-  const proxyCache = useRef(new WeakMap());
   const lastTracked = useRef(null);
   useIsomorphicLayoutEffect(() => {
     lastTracked.current = {
@@ -109,7 +109,7 @@ export const useReduxState = (opts = {}) => {
     const unsubscribe = store.subscribe(callback);
     return unsubscribe;
   }, [store]); // eslint-disable-line react-hooks/exhaustive-deps
-  return createDeepProxy(state, affected, proxyCache.current);
+  return createDeepProxy(state, affected, proxyCache);
 };
 
 export const useReduxStateSimple = () => {
Benchmark: baseline with 6a5879b
Running benchmark deeptree-nested-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark deeptree-nested-useReduxState:
┌─────────┬──────────────┬────────────────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                                 │
│         │ (Mount, Avg) │                                                                            │
├─────────┼──────────────┼────────────────────────────────────────────────────────────────────────────┤
│ 52.23   │ 200.1, 0.4   │ 59,57,59,57,58,59,58,56,55,56,55,54,56,51,46,48,47,42,43,49,48,44,46,50,50 │
└─────────┴──────────────┴────────────────────────────────────────────────────────────────────────────┘
Running benchmark deeptree-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark deeptree-useReduxState:
┌─────────┬──────────────┬─────────────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                              │
│         │ (Mount, Avg) │                                                                         │
├─────────┼──────────────┼─────────────────────────────────────────────────────────────────────────┤
│ 34.86   │ 100.6, 0.7   │ 42,45,44,40,31,37,46,37,39,40,36,39,41,42,38,27,25,24,25,27,26,29,30,30 │
└─────────┴──────────────┴─────────────────────────────────────────────────────────────────────────┘
Running benchmark forms-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark forms-useReduxState:
┌─────────┬──────────────┬───────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                        │
│         │ (Mount, Avg) │                                                                   │
├─────────┼──────────────┼───────────────────────────────────────────────────────────────────┤
│ 56.76   │ 1095.0, 0.3  │ 55,54,58,55,57,56,55,56,55,56,57,58,57,58,60,58,56,59,57,56,58,58 │
└─────────┴──────────────┴───────────────────────────────────────────────────────────────────┘
Running benchmark stockticker-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark stockticker-useReduxState:
┌─────────┬──────────────┬───────────────────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                                    │
│         │ (Mount, Avg) │                                                                               │
├─────────┼──────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ 52.05   │ 240.0, 0.2   │ 53,57,58,56,60,57,54,49,48,50,55,56,52,53,52,54,51,50,49,50,48,50,48,53,47,47 │
└─────────┴──────────────┴───────────────────────────────────────────────────────────────────────────────┘
Running benchmark tree-view-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark tree-view-useReduxState:
┌─────────┬──────────────┬────────────────────────────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                                             │
│         │ (Mount, Avg) │                                                                                        │
├─────────┼──────────────┼────────────────────────────────────────────────────────────────────────────────────────┤
│ 50.32   │ 549.2, 1.3   │ 38,51,57,46,48,45,49,55,51,55,43,54,46,52,49,51,50,55,53,54,56,47,50,44,55,53,54,45,45 │
└─────────┴──────────────┴────────────────────────────────────────────────────────────────────────────────────────┘
Running benchmark twitter-lite-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark twitter-lite-useReduxState:
┌─────────┬──────────────┬─────────────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                              │
│         │ (Mount, Avg) │                                                                         │
├─────────┼──────────────┼─────────────────────────────────────────────────────────────────────────┤
│ 58.90   │ 2.7, 0.8     │ 59,60,59,60,59,60,59,60,59,60,59,60,59,60,59,57,59,56,57,59,57,59,58,58 │
└─────────┴──────────────┴─────────────────────────────────────────────────────────────────────────┘
Benchmark: with the patch
Running benchmark deeptree-nested-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark deeptree-nested-useReduxState:
┌─────────┬──────────────┬─────────────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                              │
│         │ (Mount, Avg) │                                                                         │
├─────────┼──────────────┼─────────────────────────────────────────────────────────────────────────┤
│ 52.70   │ 147.8, 0.4   │ 58,60,58,59,58,59,57,55,56,57,55,54,48,47,48,46,49,48,49,45,48,42,45,45 │
└─────────┴──────────────┴─────────────────────────────────────────────────────────────────────────┘
Running benchmark deeptree-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark deeptree-useReduxState:
┌─────────┬──────────────┬─────────────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                              │
│         │ (Mount, Avg) │                                                                         │
├─────────┼──────────────┼─────────────────────────────────────────────────────────────────────────┤
│ 39.29   │ 83.3, 0.6    │ 49,52,45,49,46,49,47,49,51,47,48,50,33,30,31,28,30,31,30,28,22,21,22,22 │
└─────────┴──────────────┴─────────────────────────────────────────────────────────────────────────┘
Running benchmark forms-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark forms-useReduxState:
┌─────────┬──────────────┬──────────────────────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                                       │
│         │ (Mount, Avg) │                                                                                  │
├─────────┼──────────────┼──────────────────────────────────────────────────────────────────────────────────┤
│ 55.99   │ 1096.6, 0.3  │ 52,49,52,53,55,56,55,57,56,60,57,56,57,56,57,58,57,58,57,55,57,56,58,57,58,57,57 │
└─────────┴──────────────┴──────────────────────────────────────────────────────────────────────────────────┘
Running benchmark stockticker-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark stockticker-useReduxState:
┌─────────┬──────────────┬─────────────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                              │
│         │ (Mount, Avg) │                                                                         │
├─────────┼──────────────┼─────────────────────────────────────────────────────────────────────────┤
│ 56.21   │ 195.2, 0.2   │ 55,59,58,60,58,57,58,57,58,54,57,56,54,56,54,53,55,53,54,55,53,51,52,52 │
└─────────┴──────────────┴─────────────────────────────────────────────────────────────────────────┘
Running benchmark tree-view-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark tree-view-useReduxState:
┌─────────┬──────────────┬────────────────────────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                                                 │
│         │ (Mount, Avg) │                                                                            │
├─────────┼──────────────┼────────────────────────────────────────────────────────────────────────────┤
│ 50.37   │ 529.4, 1.2   │ 40,51,58,45,48,43,49,54,55,46,53,46,50,53,50,56,53,55,49,51,43,51,53,44,44 │
└─────────┴──────────────┴────────────────────────────────────────────────────────────────────────────┘
Running benchmark twitter-lite-useReduxState
    Checking max FPS... (30 seconds)

Results for benchmark twitter-lite-useReduxState:
┌─────────┬──────────────┬──────────────────────────────────────────────────────────┐
│ Avg FPS │ Render       │ FPS Values                                               │
│         │ (Mount, Avg) │                                                          │
├─────────┼──────────────┼──────────────────────────────────────────────────────────┤
│ 59.07   │ 3.6, 0.8     │ 59,60,59,60,59,60,59,60,59,60,59,60,57,59,57,59,58,59,59 │
└─────────┴──────────────┴──────────────────────────────────────────────────────────┘

A bit better. (but, not that drastically?)

Another pros is keeping ref equality among hooks, so:

const MyComponent = () => {
  const state1 = useReduxState();
  const state2 = useReduxState();
  // state1 === state2
...

The cons is the tracking may not be accurate:

const ParentComponent = () => {
  const state = useReduxState();
  const foo = state.foo;
  return <ChildComponent foo={foo} />;
};

const ChildComponent = ({ foo }) => {
  const state = useReduxState();
  const foo2 = state.foo;
  return (
    <>
      <Foo foo={foo2} /> 👉 foo2 is tracked in ChildComponent
      <Foo foo={foo} /> 👉  foo is also tracked in ChildComponent although it's from ParentComponent
    </>
  );
};

I don't know what would happen if there're async calls.

@dai-shi
Copy link
Owner Author

dai-shi commented May 13, 2019

const Parent = () => {
  const state = useReduxState();
  const foo = state.foo;
  return (
    <>
      <Child1 />
      <Child2 foo={foo} />
    </>
  );
};

const Child1 = () => {
  const state = useReduxState();
  const foo = state.foo;
  return (
    <>
      <Foo foo={foo} /> 👉  foo is tracked in Child1
    </>
  );
};

const Child2 = ({ foo }) => {
  return (
    <>
      <Foo foo={foo} /> 👉  foo is tracked as used in Child1. 😵 
    </>
  );
};

I thought it would be problematic in concurrent mode, but even in non-concurrent mode, it may not track as expected.

@theKashey
Copy link

Yeah. I was thinking about patching React.createElement with "deproxify" stuff. That would solve problem of tracking continuing in another component.

@dai-shi
Copy link
Owner Author

dai-shi commented May 14, 2019

Interesting. Although, with useReduxState, we generally want to continue tracking in child components.

@theKashey
Copy link

theKashey commented May 14, 2019

Interesting. Although, with useReduxState, we generally want to continue tracking in child components.

No, this is something you don't want to do

const Parent => ({data}) => (
 <>
   <Child1 data={data} />
   <Child2 data={data} />
 </> 
)

const Child1 = ({data}) => data.stringValue;
const Child2 = ({data}) => data.stringValue[0];

💥Parent and Childs would be updated only when first - [0] - character is updated. Don't forget - the "usage" is tracking "deepest" access, thus you shall not mix different components, but build a concrete boundaries between them.

Adding deproxify to the createElement would also help to define not the deepest, but valuable dependencies. Ie the ones which actually got used

@dai-shi
Copy link
Owner Author

dai-shi commented May 15, 2019

Oh no. How do you deal with it in the first place?
Like in beautiful-react-redux? Ah, it's selector based...

In your example, the string value is not so problematic because we don't track strings.
BUT, I can imagine this:

const Parent = () => {
  const state = useReduxState();
  const { foo } = state;
  return (
    <>
      <Child1 foo={foo} />
      <Child2 foo={foo} />
    </>
  );
};

const Child1 = ({ foo }) => (
  <div>{foo.stringValue}</div>
);

const Child2 = ({ foo }) => useMemo(() => (
  <div>{foo.numberValue}</div>
), [foo]);
// Or same thing with React.memo with the second argument

I have no idea how to solve this in userland. 🤔 any workaround...

@dai-shi
Copy link
Owner Author

dai-shi commented May 17, 2019

Let me merge this and I will release it as a new version, hoping someone would try it and give us a feedback.
Your comment is always welcome here or in any other issues/PRs.

@dai-shi dai-shi merged commit 5dd100a into master May 17, 2019
@dai-shi dai-shi deleted the slimmed-deep-proxy branch May 17, 2019 15:01
@theKashey
Copy link

Everything is looking good (at least yet 🤓). Look like you nearly fixes a new patterns in React, so many people were struggling with.

@dai-shi
Copy link
Owner Author

dai-shi commented May 17, 2019

👍

a new patterns in React, so many people were struggling with.

Could you elaborate this? what do you mean by a new patterns?

@theKashey
Copy link

Sorry, 🤯🥴💩. I was trying to point on “patterns” commonly used to wire the app - in your case it’s closer to the magic of Vue (which is also backed by proxies).

There was a long standing issue with redux and selectors, which is just a now issue for you.

So you are fixing old patterns by a new ones. This is something I wanted to say ;)

@dai-shi
Copy link
Owner Author

dai-shi commented May 18, 2019

Got it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants