Speedup saving of document with a lot of xobjects

Last modified by Thomas Mortagne on 2024/11/19 16:15

Description

Saving a document which contains a lot of xobject can be very slow.

There are actually two main areas:

To reproduce

{{groovy}}
  if ('true'.equals(request.confirm)) {
    // Create a small document to gather a reference time
    def smallDocument = xwiki.getDocument('Test.DocumentSave.SmallDocument')
    def before = System.currentTimeMillis();
    smallDocument.save("Empty save")
    def after = System.currentTimeMillis();
    def totalDuration = after - before;
    println "Saving the empty document took **${totalDuration}ms**"

    // Create the big document if it does not exist yet
    def testDocument = xwiki.getDocument('Test.DocumentSave.BigDocument')
    if (testDocument.isNew()) {
      def testClass = testDocument.getxWikiClass().getXWikiClass()
      testClass.addTextField("property", "Tests Property", 30)
      for (int i = 0; i < 10000; i++) {
        def testObject = testDocument.newObject('Test.DocumentSave.BigDocument')
        testObject.set('property', "value${i}")
      }
      before = System.currentTimeMillis();
      testDocument.save("Initial setup")
      after = System.currentTimeMillis();

      totalDuration = after - before;
      println "Creating the the big document with 10000 xobjects took **${totalDuration}ms**"
    }

    // Re-save the document with a new xobject
    testDocument = xwiki.getDocument('Test.DocumentSave.BigDocument')
    def testObject = testDocument.newObject('Test.DocumentSave.BigDocument')
    testObject.set('property', "extra")

    before = System.currentTimeMillis();
    testDocument.save("Add xobject")
    after = System.currentTimeMillis();

    totalDuration = after - before;
    println "Saving the big document with a new xobject took **${totalDuration}ms**"
  } else {
    print '[[confirm>>?confirm=true]]'
  }
{{/groovy}}

Result

Information

Database: MySQL 8.0.36
Java: 17, in debug mode (so slower than production)

Also added some more detail on what exactly happen in each step of the script.

Create empty document: 104ms
  • Before save: 0ms
    •  Updating the document archive: 3ms
      •  Creating the patch: 2ms
        •    Full serialization: 2ms
    •  XWikiDocument save: 0ms
    •  Xobjects save: 0ms
    •  Updating the space table: 0ms
    •  Applying the transaction: 30ms
  • After save: 70ms
Resave empty document: 107ms
  • Before save: 0ms
    •  Updating the document archive: 1ms
    •  XWikiDocument save: 0ms
    •  Xobjects save: 0ms
    •  Updating the space table: 1ms
    •  Applying the transaction: 27ms
  • After save: 77ms
Create big (10000 objects) document: 8387ms cancel
  • Before save: 0ms
    •  Updating the document archive: 115ms
      •  Creating the patch: 113ms
        •    Full serialization: 113ms
    •  XWikiDocument save: 0ms
    •  Xobjects save: 1911ms error
    •  Updating the space table: 0ms
    •  Applying the transaction: 3424ms error
  • After save: 2931ms error
Add xobject to big document: 260920ms cancelcancel
  • Before save: 0ms
    •  Updating the document archive: 253328ms
      •  Creating the patch: 253326ms
        •    Full serialization: 87ms
        •    Diff: 253229ms cancel
    •  XWikiDocument save: 1ms
    •  Xobjects save: 1939ms error
    •  Updating the space table: 0ms
    •  Applying the transaction: 2921ms error
  • After save: 2722ms error

 

Get Connected