beenotung / dom-proxy

Develop lightweight and declarative UI with automatic dependecy tracking without boilerplate code, VDOM, nor compiler
https://www.npmjs.com/package/dom-proxy
BSD 2-Clause "Simplified" License
29 stars 1 forks source link

Interested in performance as proxies add an additional layer of indirection #1

Open geekburton opened 6 months ago

geekburton commented 6 months ago

Firstly, great library and idea. It's refreshing to see more alternatives to the VDOM.

I'm very interested to see how this benchmarks against the incremental-dom approach which Angular uses for it's rendering engine (Ivy).

Also, you mentioned:

we don't need to run "diffing" algorithm on VDOM to reconciliate the UI.

Which makes sense, but perhaps doing this via a proxy will create a similar memory overhead from the proxy creation and indirection that proxies introduce?

I think this would be a fun and helpful thing to collaborate on - if you don't already have such benchmarks available.

Would love to hear your thoughts.

beenotung commented 6 months ago

Thanks for the suggestion. It's an good idea to benchmark proxy-approach vs incremental-dom approach.

The main feature of dom-proxy is to automatically perform updates when the depending state is changed. And the state is kept directly in the dom instead of maintaining another data model in Javascript runtime, which make it easier to work with other codes not specifically written with this library in mind.

This library wrap the dom object into a proxy object, which incurs memory overhead and computation overhead for the benefit of allowing less verbose code and enable hybrid of declarative UI and imperative updates. The updates can perform mutation directly, without creating an new objects like React requires.

In another hand, the incremental-dom approach seems to incur less overhead than the virtual-dom approach. It is unsure whether the incremental-dom approach is more efficient than the proxy approach. A benchmark should be able to provide some insights.

A side note. I made another library "data-template" which write the UI template in html. And apply data from Javascript, with support to do conditions and loops. This library doesn't comes with reactive design. It should be incuring much less overhead. You may use it directly or in combination with dom-proxy. https://github.com/beenotung/data-template

geekburton commented 6 months ago

My pleasure and thanks for your response and i'll have a look at the data-template library you wrote too.

I'm doing some comparison testing and it appears that there are some performance issues. For context, i've set up a proxy for an element and am updating the data dynamically via a setInterval:

export function renderDomProxy(value: number): void {
    let { container } = queryElementProxies({
        container: 'div#proxy-dom-container'
    });

    watch(() => {
        container.textContent = `${value}`;
        console.log(container.textContent);
    })   
}

setInterval(() => { renderDomProxy(Math.random()) }, 1000);

Which results in a Uncaught RangeError: Maximum call stack size exceeded.

Is there something the library needs to optimise updates?

dom-proxy-update-test

geekburton commented 6 months ago

Ok i've fixed the issue, here is the latest so far:

Incremental DOM took 2.4000000953674316 milliseconds.
main.ts:30 DOM-PROXY took 0.20000004768371582 milliseconds.
incremental-dom.ts:13 Incremental DOM took 0.09999990463256836 milliseconds.
main.ts:38 DOM-PROXY took 0.09999990463256836 milliseconds.

This is based on a simple text update as I showed in the gif above. dom-proxy seems to appear much faster on the initial render, but then performance becomes comparable after that. My hypothesis is that it has to do less as it's closer to the DOM, but once it's rendered, the incremental-dom approach is able to optimise its rendering.

We need some further testing with more complex rendering to see, but interesting results so far. I'll add to this as and when I have the time.

beenotung commented 6 months ago

I suppose dom-proxy is doing less or similar amount of (user-land) code than incremental dom. The overhead of the proxy API depends on the browser-specific implementation, which may vary among different versions.

Incremental dom is intended to be generated from template instead of being written by application developer directly for productive developer experience. And I suppose incremental dom doesn't comes with reactive update mechanism?

So comparing them directly on micro operations may not reflect the actual behavior when used to develop a complete application.

You may try to develop a more complete application with both approaches then compare the performance and developer experience.

geekburton commented 6 months ago

Agreed, a more comprehensive comparison with more deeply nested DOM changes will be more helpful.