-
Notifications
You must be signed in to change notification settings - Fork 15
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
Refactor to minimize the number of redundant iterations #40
Conversation
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit 3d45aec:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on it! Started to slowly review the code. Here's the first question.
const index = Number(op[1][op[1].length - 1]); | ||
if (!Number.isFinite(index)) return []; | ||
return [[op[0], index, op[2], op[3]]]; | ||
export const parseProxyOps = (ops: Op[]): Record<string, ArrayOp[]> => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't there a way to do it without changing the signature?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could maybe call it partitionedProxyOps
, call that from subscribeP
and leave the original as is, or you were thinking of a different option?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm thinking not changing the exported function at all. I might be missing your refactoring point though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The refactor makes sure parseProxyOps is called one time. And arrayOps are processed on a per path basis.
Maybe my question is whether we can ensure calling the function once, without processing on a per-path basis.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got you. Yes, we could do that. But then there is no escaping the redundant runs that happen in the aOps
forEach.
So below I am just printing the number of iterations for the below example
import * as Y from 'yjs';
import { proxy } from 'valtio/vanilla';
import { bind } from '../src/old/index';
const initData = [...Array(9).keys()];
test.only('dev', async () => {
const doc = new Y.Doc();
const a = doc.getMap('arr');
const p = proxy<any>({
x: [...initData],
y: [...initData],
z: [...initData],
i: [...initData],
j: [...initData],
k: [...initData],
});
bind(p, a);
(() => {
p.x.reverse();
p.y.reverse();
p.z.reverse();
p.i.reverse();
p.j.reverse();
p.k.reverse();
})();
expect(true).toBe(true);
});
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would use a WeakMap for snapshot(proxyObj)
to avoid the duplication.
I wonder if we can write a failing test firstly.
const pathkey = path.join('.'); | ||
if (!(pathkey in arrayOpsAll)) return; | ||
const arrayOps = arrayOpsAll[pathkey]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the use of pathkey
important of the refactoring? Maybe so.
I'm not a big fan of usign .
delimiter. What if a path includes the dot?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it would be of impact here, since we never break on .
again, it's merely just a concatenated representation for the parent path, so we can use it as a key to refer to a collection of arrayOps together.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically, ["a.b", "c"]
and ["a", "b.c"]
can conflict.
I like the idea to improve the performance, bug #40 (comment) is not acceptable. |
I was going through the code and noticed that
SubscribeP
function andparseProxyOps
are a bit confusing as there are redundant iterations going on there.parseProxyOps
works on the whole set of operations, but those could be related to different paths, yet it's still being called multiple times for each operation.The refactor makes sure
parseProxyOps
is called one time. And arrayOps are processed on a per path basis.