Transact update size issue

I observed an unexpected result when using YDoc.transact(), hoping someone can shed some light. Here is the minimal repro:

import * as Y from 'yjs'

const yDoc = new Y.Doc()
const yMap = yDoc.getMap()

yDoc.on('update', (update) => {
    console.log('update length:', update.length)
})

yDoc.transact((tr) => {
    for (let x = 0; x < 1000; x++) {
        yMap.set('a', x)
        //yMap.set('b', x)
    }
})

As written the update observed length is 37, which is around what I’d expect. However, if I un-comment the setter on ‘b’, the update size becomes 17,891.

Is that expected? If yes, how does one use YDoc.transact() such that the changes are collapsed to a reasonable fixed size?

Cannot comment on why this happens - also interested!

Just noticed that in your example you’re setting the same value all over again for a thousand times. If you have similar issues in your production code, you can always check if the current value already matches the desired one. That’s what I did in some case where I found out that my application was creating unnecessary updates. Y.js itself doesn’t seem to have a mechanism for “oh, it already has the same value, let’s skip this one”.

See notes under Y-KeyValue:

1 Like

This sounds fantastic I will give it a try shortly, thank you. Is there any downside? I’m wondering why Yjs doesn’t just work this way out of the box?