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

Performance problem with multiple block nodes #911

Open
vladimirvrabel opened this issue Apr 10, 2019 · 5 comments
Open

Performance problem with multiple block nodes #911

vladimirvrabel opened this issue Apr 10, 2019 · 5 comments

Comments

@vladimirvrabel
Copy link

vladimirvrabel commented Apr 10, 2019

Scenario:

Creation a PM document from a text, where each word of text has a custom attributes, which will be reflected into node attr structure.

Issue details

There is a typing performance / delay issue. Interesting thing is, that there is no performance issue when there is decorated only one custom_text node instead 3000 and more nodes at the same time.

<!DOCTYPE html>

<html>

<head>
    <meta charset="UTF-8"/>
</head>

<body>

<!--
    Compiled node modules from https://www.npmjs.com/search?q=prosemirror into one js file via http://browserify.org/
    prosemirror-state -> 1.2.2
    prosemirror-view -> 1.8.7
    prosemirror-schema-basic -> branch from 1.0.0, where only "nodes" struct was changed
      var nodes = {
        doc: {
            content: "block+"
        },

        paragraph: {
            content: "block*",
            group: "block",
            toDOM: function toDOM() { return ["p", 0] }
        },

        custom_text: {
            attrs: {
                index: { default: -1 },
                start: { default: -1 },
                end: { default: -1 },
            },
            content: "inline*",
            group: "block",
            toDOM: function toDOM() { return ["span", 0] }
        },

        text: {
            group: "inline"
        }
      };

  Browserify compiled js file:
    // 1.2.2
    const  {EditorState, Plugin} = require('prosemirror-state');
    // 1.8.7
    const  {EditorView, Decoration, DecorationSet} = require('prosemirror-view');
    // modified node (from 1.0.0)
    const  {schema} = require('./subtitle_editor_schema.js');

    GProsemirrorState = EditorState;
    GPlugin = Plugin;
    GEditorView = EditorView;
    GDecorationSet = DecorationSet;
    GDecoration = Decoration;
    editorSchema = schema;
 -->
<script src="subtitle_editor_compiled.js" defer></script>

<div>
    <div>
        <div>
            <div id=editor></div>
        </div>
    </div>
</div>

<script>
    var cachedDecorationSet = null;

    window.onload = function() {
        initializeEditor();

        cachedDecorationSet = GDecorationSet.create(editorView.state.doc, [
            GDecoration.inline(0, editorView.state.doc.content.size, {style: "color: purple"})
        ]);

        editorView.updateState(editorView.state)
    };

    initializeEditor = function () {
        highlightPlugin = new GPlugin({
            props: {
                decorations(state) {
                    return cachedDecorationSet;
                }
            }
        });

        let items = dumbData();
        let docNodes = [];
        let paragraphNodes = [];

        for (let item of items) {
            paragraphNodes.push(editorSchema.node("custom_text", {index: item.index}, [editorSchema.text(item.text)]));
        }

        if (paragraphNodes.length > 0) {
            docNodes.push(editorSchema.node("paragraph", null, paragraphNodes));
        }

        let doc = editorSchema.node("doc", null, docNodes);

        let state = GProsemirrorState.create({
            doc: doc,
            plugins: [
                highlightPlugin,
            ]
        });

        editorView = new GEditorView(document.querySelector("#editor"), {
            state: state,
        });
    };

    function dumbData() {
        let arr = [];
        for (let i = 0; i < 6000; i++) {
            let text = i % 2 ? " " : i.toString();

            arr.push({
                id: i,
                text: text,
            });
        }

        return arr;
    }

</script>
</body>

Demo:

https://glitch.com/edit/#!/bronzed-drug?path=index.html:6:27

Related issue:

Because ProseMirror treats text nodes as just plain text, there is need to find workaround (custom nodes) for scenario described above. More at the issue #910

Could you help me with it, please?

Thank you

Vlado

marijnh added a commit to ProseMirror/prosemirror-view that referenced this issue Apr 11, 2019
FIX: Improve display update times for nodes with thousands of children
by fix an accidental piece of quadratic complexity.

Issue ProseMirror/prosemirror#911
@marijnh
Copy link
Member

marijnh commented Apr 11, 2019

Ah, oops, that was a case of accidentally quadratic complexity. Could you try if attached patch helps for you? Performance of inline nodes with tons of children is still not super great, but better than before, and it seems that the remaining slowness is largely coming from the browser's layout and redraw code.

@vladimirvrabel
Copy link
Author

vladimirvrabel commented Apr 11, 2019

It looks, that you fixed performance for document without decorations. There was a lag at the end of document before. Could you be able to make a fix when decorations are turned on? Here is test environment with applied fix https://glitch.com/edit/#!/slash-celsius?path=index.html:79:6

@marijnh
Copy link
Member

marijnh commented Apr 15, 2019

What do you mean by decorations being turned on? Your demo is a bit hard to figure out due to some of the relevant code being hidden in that huge bundle, but when I try to replicate it (a paragraph with lots of nodes, each being separately decorated), I'm not seeing any performance issues. Could you simplify the demo?

@vladimirvrabel
Copy link
Author

I noticed, that you released prosemirror-view 1.8.9. Here is updated demo(updated to prosemirror-view 1.8.9) https://glitch.com/edit/#!/grizzled-change?path=index.html:134:0 where I made a more comments. I think, that you will be able to reproduce an issue when you will use subtitle_editor_schema.js(because we want to add a attribute into text node -> discussion at #910) and will create decorations on cca 12000 "custom_text" nodes (I created a helper methods for it)

@vladimirvrabel
Copy link
Author

vladimirvrabel commented Apr 23, 2019

But when you use a default schema from prosemirror-schema-basic and create cca 12000 paragraphs with at least one text node and will make a decorations for it, than you will see a performance problem during editation too. Demo(with prosemirror-view 1.8.9) for it: https://glitch.com/edit/#!/accidental-slope?path=subtitle_editor.js:6:51

Edit:
Updated into prosemirror-view 1.11.3 (issue still persists)
https://glitch.com/edit/#!/diligent-nannyberry?path=subtitle_editor.js:3:9

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

No branches or pull requests

2 participants