-
Hey Ryan! I've resumed my work on researching efficient rendering strategies for conditional paths. I tried to create a benchmark between Solid and Ivi looking at conditionals inside map. Below is an example code: <Show when={state.done === false}>
<For each={array}>
{x => {
return <For each={array}>
{y => {
if (x > y) {
return <div>Ok</div>
}
return null;
}}
</For>
}}
</For>
</Show> How did you approach this? Basically, if you have a map -> condition -> map -> condition situation, do you render it inside out or outside in? |
Beta Was this translation helpful? Give feedback.
Replies: 10 comments 2 replies
-
My I'm interested in what you find. Direct cascading control flows, like Fragments produce the most potential for de-opt. My original approach here might have been the most performant but it was super complex, where I was basically virtualizing fragments throughout the tree. My newer approach basically attempts to normalize the whole array so while it is shallow comparisons.. there are definitely places where I do more checks than theoretically needed. It was a good balance for code size, and made Solid even faster in the simple cases, but I do wonder just how much this gives up. |
Beta Was this translation helpful? Give feedback.
-
Actually looking at your example does x/y ever change? If not what you have should be fine. In this case, I do render outside in since I can't prematurely create things we won't use. |
Beta Was this translation helpful? Give feedback.
-
I had some trouble setting up Solid and getting it to work. This was the example I tried to port from ivi. const t1 = Date.now();
let done = false;
let array = [1,2,3,4,5,6,7,8,9,10];
let items = ['Hello', 'Some', 'Great', 'World'];
function App() {
if (done) {
setTimeout(function() {
const t2 = Date.now();
alert('Time elapsed: ' + (t2 - t1));
});
return 'Done';
} else {
return array.map(x => {
return x < 2 ? null : array.map((x,i) => {
if (i < 4) {
return div(_, _, 'Larger than 4');
} else if (i > 4 && i < 6) {
return null;
} else {
return items.map((item, i) => {
if (i > 1) {
return div(_, _, item);
}
return null;
});
}
});
});
}
}
const root = document.getElementById('app');
render(App(), root);
array = [11,12,13,14,15,16,17,18,19,20];
items = ['Some', 'Other', 'World', 'What'];
render(App(), root);
array = [1,6,1,7,2,8,1,9,12,14,1,15];
items = ['There', 'Is', 'Still', 'Hope'];
render(App(), root);
done = true;
render(App(), root); |
Beta Was this translation helpful? Give feedback.
-
All right, yeah, I recognized the code from S array but helpful to know which approach you went for. I created a few new repositories. You can track my progress there. Anod is basically a merge of S and S array, where I experiment with mutation propagation for array procedures. Haven't decided if I will purse tracking or subclocks there yet. Also experimenting in isolit, creating a merge of a virtual dom and data binding approach. The idea is to set up an entire virtual dom and then only patch it from data bindings. So then we would basically have virtual nodes all the way down, something like EnumerableOp -> childNodes Op[] -> ProcedureOp -> EnumerableOp etc. |
Beta Was this translation helpful? Give feedback.
-
I see they do change.. drastically too. Nothing shared. It basically re-renders everything if this is keyed. Is the intention for this to be keyed or non-keyed? With primitives like this, it feels you want non-keyed in which case I'd use
Vue works something like this I think. |
Beta Was this translation helpful? Give feedback.
-
The idea was to reuse very little (you see that some nodes can be reused in the last part). It's based on the example Boris had on Ivi (but I think it was dropped from docs upon 1.0), where he tested performance of conditional rendering in maps, where ivi basically had no performance penalty of conditionals as it doesn't matter from the virtual dom perspective. So I wanted to see how big of a slowdown the data driven approach has and how to mitigate it. |
Beta Was this translation helpful? Give feedback.
-
I see so this is keyed by the value not by the index? Like from initial to 2nd with how Let me see if I can recreate this for you. |
Beta Was this translation helpful? Give feedback.
-
Ok not promising this is super optimized but I think I recreated the logic: https://codesandbox.io/s/ivi-example-zsopf?file=/index.js. Using indexes in That all being said make sure you are testing the same thing. Keyed, vs non-keyed makes a big difference and I can't tell from the code if ivi is doing keyed or not. I do suspect there will be overhead here as this example is pretty complicated logic-wise and the benchmark is basically doing snapshots so there is almost no benefit to even diffing. No partial updates either. Benefit of reactivity is to reduce work and this example there is basically no opportunity to. I suspect a naive innerHTML would give both frameworks a run for their money. Even more exaggerated by only having single div insertion so the benefits of node cloning one of perf gains over VDOM which is more present in typical apps is lost here. Mind you if I wanted to come up with an example to showcase ivi this would be it. |
Beta Was this translation helpful? Give feedback.
-
You're absolutely right. I will set up a repository with some more thought through benchmarks. Will definitively keep in mind keyed vs non-keyed. By the way, it might interest you, but I have now pushed a much more performant tracing solution. It lazily evaluates tracing and opts for static dependency trees. Also entirely removes the awkward dependee part, and updates traces like subclocks, e.g. they always run before normal updates, so once they are run, we don't have to check upstream dependencies of downstream nodes as we know any tracking nodes have already been executed. |
Beta Was this translation helpful? Give feedback.
-
I've setup my most current research in anod. It offers tracing computations and my idea of array mutation propagation. Would love to hear your thoughts about it! Some powerful features involve tracing computations for all array operations, i.e., methods like I've started adding docs to it as well. It's still a work in project and I'm trying to catch up on all required unit tests. |
Beta Was this translation helpful? Give feedback.
Ok not promising this is super optimized but I think I recreated the logic: https://codesandbox.io/s/ivi-example-zsopf?file=/index.js. Using indexes in
<For>
actually adds a memory overhead that I optimize out when not required. And<Switch>
<Match>
is likely not the most optimal way to do the conditional logic but it is definitely the easiest.That all being said make sure you are testing the same thing. Keyed, vs non-keyed makes a big difference and I can't tell from the code if ivi is doing keyed or not.
I do suspect there will be overhead here as this example is pretty complicated logic-wise and the benchmark is basically doing snapshots so there is almost no benefit to even diffing. …