Premium support for our pure JavaScript UI components


Post by Maxim Gorkovsky »

After running a profile I figured where does performance degradation come from. Recently we changed Model code to deep clone incoming data. In our demos we use simple objects for events so it doesn't make a difference. But in your dataset event object is huge and has nested fields, so deep cloning it takes significant time.
Good news is that you can modify that behavior with a config. For example, enabling this brings performance to the same level as we saw in profiles that were taking above:

new Scheduler({
  eventStore : {
    useRawData : true
  }
})

This config will disable deep cloning as well as some other data sanitation tricks (duplicate ids etc), you can read more about them here: https://bryntum.com/docs/scheduler/#Scheduler/data/EventStore#config-useRawData
Please try it out and let us know of the result.


Post by asd »

Hi Maxim,

I updated the config as mentioned, I do see the performance improvement from 1700milliseconds(refer screenshot attached in prev comment) to 1300milliseconds(attaching the screenshot with this post). Tried this with 4.2.5 version.

But I still see the numbers not matching or better from 3.1.9 version which is 950milliseconds(Attaching the screenshot with this post)

As mentioned earlier this is one instance or area where I see the performance issue, the other area is after the events are added there is delay of events being displayed on the scheduler.

Scheduler version 4.2.5
Scheduler version 4.2.5
scheduler_4.2.5.png (922.77 KiB) Viewed 869 times
Scheduler version 3.1.9
Scheduler version 3.1.9
Scheduler_3.1.9.png (918.69 KiB) Viewed 869 times

Post by Maxim Gorkovsky »

In this testcase I see a different picture:

const scheduler = new Scheduler({
    appendTo         : 'container',
    minHeight        : '20em',
    startDate        : new Date(2021, 0, 1),
    endDate          : new Date(2021, 1, 1),
    viewPreset       : 'hourAndDay',
    rowHeight        : 50,
    barMargin        : 5,
    multiEventSelect : true,

    resourceStore : {
        tree : true,
        data : resources // resources from your archive
    },

    eventStore : {
        useRawData : true
    },

    features : {
        tree : true
    },

    columns : [
        { type : 'tree', text : 'Name', field : 'name', width : 130 }
    ]
});

const newEvents = [];

function getRandomInt(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min) + min);
}

for (let i = 0; i < 4000; i++) {
    newEvents.push({
        id         : i,
        resourceId : 'r' + getRandomInt(1, 11),
        name       : 'Team scrum ',
        startDate  : DateHelper.add(scheduler.startDate, i, 'h'),
        endDate    : DateHelper.add(scheduler.startDate, i + 1, 'h'),
        location   : 'Some office',
        eventType  : 'Meeting',
        eventColor : '#ff0000',
        iconCls    : 'b-fa b-fa-users'
    });
}

let t0, t1;

t0 = performance.now();
scheduler.eventStore.add(events); // events from your archive
t1 = performance.now();
console.log(`Call to eventStore.add took ${t1 - t0} milliseconds.`);

t0 = performance.now();
scheduler.eventStore.add(newEvents);
t1 = performance.now();
console.log(`Call to eventStore.add took ${t1 - t0} milliseconds.`);

This snippet logs

// 3.1.9
Call to eventStore.add took 171.39999985694885 milliseconds.
Call to eventStore.add took 51.39999985694885 milliseconds.

// latest nightly
Call to eventStore.add took 154 milliseconds.
Call to eventStore.add took 110.09999990463257 milliseconds

As you see, your data is loaded faster to the empty store. Next 4k dummy events are loaded slower to the filled store although time is proportional to the larger dataset (154 / 5200 * 4000 > 110).

I see that 4.2.4 takes 1.5 times more time to load events on your end, which we don't see locally. It might be related to store features enabled, or store listeners or smth else.

This is why we are asking for a runnable test case - it is likely we use different approach and will not see the same problem. I understand it might be problematic to create a runnable test case especially for large application. We can try simpler steps for now, for example examining your app configuration. We can try replicating it locally to check if it affects performance. We could also benefit from a recorded profile of the page, if it contains original method names from our bundle (best would be to have two, for 3.1.9 and 4.2.4)

On your end you can try disabling extra features/listeners to see if some of them affect performance significantly.


Post by asd »

Hi,

As mentioned above we did try removing the listeners, working hours from the scheduler and measuring the performance, not much improvement the result was around 1000milliseconds.

Also instead of our existing event object we tried the dummy event object from the previous code comment, we did notice the same result i.e around 1200milliseconds for 5k events.

Other observation was assigning the event to the respective resource is taking time, once by mistake we had added duplicate key "id" we were able to repro the performance issue in your examples set also. Not sure if this helps.

Getting the runnable test case is bit tricky as of now, sending you the profile and config which we are using.

Thanks,
Abhay

Attachments
Bryntum_Data.zip
(13.83 MiB) Downloaded 61 times

Post by Maxim Gorkovsky »

I'm afraid recorded profile doesn't help much. 3.1.9 doesn't include main thread and 4.2.4 only has a 240ms task which appears to be react internals.

But nevertheless, I managed to reproduce the performance degradation in UMD bundle and opened a ticket for us to investigate: https://github.com/bryntum/support/issues/3392

UMD bundle doesn't use modern JS API and uses polyfills/transpilation to be compliant with ecmascript5. It is likely performance degradation is caused by them, we will check what we can do about that.

Workaround would be to switch to modules bundle, it uses modern JS syntax and, according to my measurements, it works a bit faster loading your data than older 3.1.9 edition. If you do not support IE11, transition should be fairly easy - it should be enough to replace the bundle and change imports.


Post by sergey.maltsev »

Hi, asd!

As I mentioned above umd bundle for Scheduler would be less preferable than existing module one in terms of performance.
This happens because umd was built with ie11 target preset.
We will remove ie11 support in coming releases, stay tuned to updates notifications.

For now the solutions is to switch to scheduler.module.js bundle or create less "heavy" umd bundle for modern browsers with webpack.

You may use this simple project for this:

bryntum-retranspile.zip
(1.09 KiB) Downloaded 60 times
  • Unpack it to any folder
  • Copy scheduler.module.js from Scheduler distribution zip to lib folder of the project
  • Run from project's root
    npm i
    npm run build
  • Replace old umd bundle with newly created scheduler.umd.js from build folder

This would help to fix performance issue.

Also please note that using of https://www.bryntum.com/docs/scheduler/#Core/data/Store#config-useRawData store config suggested by Maxim would also improve performance.

    eventStore : {
        useRawData : true
    },

Looking forward for your test results.


Post by asd »

Hi,

I did take the transpiled code from scheduler.module as mentioned above, but am getting some error like "constructor not able to call without new method for " DraggerHelper.

Below is the sample code which am using

class Drag extends window.bryntum.scheduler.DragHelper {
  static get defaultConfig() {
    return {
      // Don't drag the actual row element, clone it
      cloneTarget: true,
      mode: 'translateXY',
      dropTargetSelector: ['.b-sch-timeaxis-cell', '.b-sch-style-plain'],

  // Only allow drag of row elements inside on the unplanned grid
  // targetSelector: '.b-grid-row',
  targetSelector: '.rt-tr-group',
};
  }

  construct(config) {
    const me = this;

super.construct(config);

me.on({
  drag: me.onTaskDrag,
  dragstart: me.onTaskDragStart,
  drop: me.onTaskDrop,
  thisObj: me,
});
  }
  }

Also what is the ETA for https://github.com/bryntum/support/issues/3392 ?, i don't see it being attached to any milestone?

Thanks,
Abhay


Post by sergey.maltsev »

Hi!

Please attach some app example we can run.
Our examples work fine with the umd, created from the project above.


Post by sergey.maltsev »

This might be also related to babel-loader and ES6 code handling there.
Please check if you use v7 or above.

Please check webpack info here.
https://webpack.js.org/loaders/babel-loader/


Post by asd »

Hi,

The above error was due to classes were not being transformed, after fixing we did take the umd bundle generated from module bundle, also we are using the config

eventStore:{useRawData: true}

.

Unfortunately we don't see any improvements in the numbers. We are still seeing it to be around 1665.0999999940395 milliseconds for 5k events.

Once again attaching the profile if it might help you any further.

Thanks,
Abhay

Attachments
Profile.zip
(19.29 MiB) Downloaded 64 times

Post Reply