chartjs / Chart.js

Simple HTML5 Charts using the <canvas> tag
https://www.chartjs.org/
MIT License
64.77k stars 11.92k forks source link

Performance regression in Chart.js 3.x vs. 2.x #10073

Open mackuba opened 2 years ago

mackuba commented 2 years ago

Expected behavior

I have a site that shows various graphs of Covid-19 spread in different countries and regions, at https://mackuba.eu/corona/, which uses Chart.js. I've been maintaining it since March 2020, and at the beginning the charts worked fine since there wasn't much data to show, but the datasets were getting longer and longer, and last year already it was working kind of slow. It's especially bad in Chrome and Firefox, surprisingly it's much better in Safari.

I've built it in Chart.js 2.x, since 3.0 only came out last year. I read that 3.x includes some performance improvements, so I thought it would fix the problem.

I struggled for some time with an issue with TypeScript definitions, which changed in 3.x, but I couldn't figure it out and in the end I worked around it by marking all Chart.js types as any.

I managed to update all the calls to Chart.js to the 3.x API and started testing the site. The result was… unexpected. The site seems to work just as slow in Chrome, but now it also works slower in Safari…

I've managed to extract a minimal code sample that shows the issue to a new repo: https://github.com/mackuba/chart_slow_demo. It's a bit of an extreme example, because it shows 20 datasets with the full date range (since March 2020), and normally there's a few up to 10 datasets and a smaller date range - but this way the problem is more obvious. You can make the chart "lighter" by removing some items from the population dictionary.

Current behavior

In Chrome (Brave):

In Safari:

I'm testing this on 2018 MacBook Pro (macOS 11.6.2) - if you're checking it on a fast computer like M1 Macs and it loads immediately, try on an older machine.

Safari version: Version 14.1.2 Brave version: Version 1.34.80 Chromium: 97.0.4692.71 (Official Build) (x86_64)

Reproducible sample

https://github.com/mackuba/chart_slow_demo

Optional extra steps/info to reproduce

No response

Possible solution

No response

Context

No response

chart.js version

v3.7.0

Browser name and version

Safari 14.1.2

Link to your project

No response

mackuba commented 2 years ago

I'm not sure if this will display - I made a video that shows the difference, first v. 2.9 and then 3.7:

https://user-images.githubusercontent.com/28465/149399803-79a1c328-dfd1-4ac4-9b27-104c2aa9a19d.mp4

kurkle commented 2 years ago

There are a few things that you can use to improve speed.

  1. disable points, only draw the line. (pointRadius: 0)
  2. switch to time scale
  3. convert data to {x: timestamp, y: value} format. set parsing: false. don't need the nulls anymore, so remove those.
  4. disable animation

I played around with your sample repo a bit, did steps 1 and 2 + tested zoom plugin. You can see my tests here: https://github.com/kurkle/chart_slow_demo

mackuba commented 2 years ago

Hey,

thanks for the ideas - I'm doing some experiments with this, I'll see if anything helps.

mackuba commented 2 years ago

@kurkle Ok, here's what I'm seeing:

  1. Disabling animation:

    • obviously, much faster in Safari - but visually this isn't as nice, of course
    • about as fast on v3 as on v2 - which would imply the 3.x slowdown is in the animations area
    • Chrome still takes about ~1s before it starts to react
  2. Disabling points:

    • more fluent animation in Safari (v2) - although it obviously looks different, I need to think if I want it this way
    • even with no points, there is still a ~1s delay in v3 in Safari (!) and then it animates fluently once it's finished the work
    • Chrome works much faster without points (but still a delay in v3)
  3. Time scale:

    • no noticeable difference
  4. Time scale with data objects:

    • there is a slightly shorter delay in v3, but still slower than v2

Does it make sense to even try data objects {x,y} without a time scale? (I don't even know how to do that, the line doesn't render properly)

So my conclusions for now are:

As for the v3 slowness, it seems to me that it's something about… pre-calculating animations? Because the delay (which isn't visible in v2) goes away if I disable animations, but it happens before the animations start visually happening (for ~1s after you click the checkbox nothing happens, even the checkbox doesn't get un-clicked and the chart is static, and only a moment later it animates; this happens even with points off, in which case the chart animates pretty fluently in Safari after that delay).

ghost commented 2 years ago

Following this issue. I am seeing similar performance problems. My application is a set of dashboards with charts. As I move from one dashboard to another and back, each render takes 1 second longer and keeps accumulating as I go back and forth. It feels almost like a memory leak type of issue where prior data applied to a chart isn't cleaned up prior to rendering the new data set.

kepelrs commented 2 years ago

I'm experiencing the same issue as OP. Applied the recommendations from https://www.chartjs.org/docs/3.8.0/general/performance.html without significant improvements unless I disable animations (which is not an option in my context)

dgavey commented 2 years ago

Seeing significant performance issues between 3.X and 2.9.3. This is to the point that the browser renderer process will lock up given enough time.

Orillian commented 2 years ago

Has there been any headway on this? In testing these issues continue even with the latest release. 😞

@LeeLenaleee you closed the related ticket above as not planned?

LeeLenaleee commented 2 years ago

Closed it because it's a duplicate

naviln commented 1 year ago

I just want to add my concern about performance, as mentioned in https://github.com/chartjs/Chart.js/issues/10637 as well. I have recently upgraded from chartjs 2.9.3 to 4.1.1.

Unfortunately, the 'performance' problem is impacting other things very negatively. Note that the charts themselves appear to be performing fine - I can interact with them without problems.

Apart from the charts, I have other elements on my dashboard page, including bootstrap collapse sections, items that have tooltips and can be interacted with and clicked on.

On chartjs 2.9.3, the dashboard page was performing fine. I can hover on elements, click them, and the page responds almost instantly. After the upgrade, all the other elements on my page have become laggy and slow to respond to clicks. It takes a frustratingly obvious 2-3 seconds to interact with anything.

If I hide/remove all the charts, the performance improves again, back to how it was with 2.9.3. Reverting back to 2.9.3 seems to be the only solution at this stage.

I hope someone has some clues as to why the chart performance has dropped so rapidly! Even disabling chart animations did nothing to improve my page performance.

I tried recording using the performance monitor in chrome for more details. Miraculously, while the recording is taking place, the issue goes away! My page performance returns to normal. As soon as the recording is stopped, it returns to the choppy performance.

My project is using angular 14, and my suspicion is that the chartjs 4.1.1 is messing with the angular rendering pipeline, causing all my other elements to be reevaulated slowly and costing page performance on any dom interaction (via angular).

Does anyone have any comment or suggestions as to why this might be the case?

I have inspected and compared 2.9.3 vs 4.1.1 in the dom, and I noticed that the new version is missing something called a chartjs-render-monitor and chartjs-size-monitor. Could this be a clue? Or is there something else in the canvas that is interfering and causing issues for frameworks (like angular, in my case).

kurkle commented 1 year ago

@naviln maybe some issue in resizing? Try responsive: false in the charts options, does it make a difference?

naviln commented 1 year ago

@naviln maybe some issue in resizing? Try responsive: false in the charts options, does it make a difference?

Thanks for the response @kurkle. I've tried setting options.responsive to false, but the same problem remains.

Any other ideas or options?

kurkle commented 1 year ago

Any other ideas or options?

No other ideas, would need a reproduction to find out the cause.

bertrandp commented 1 year ago

Hi, we also have a performance regression issue when migrating from 2.x.x to 4.x.x. Here is a diff when calling chart.update() on a line chart.

With 2.x.x, it takes 180ms :

image

With 4.x.x, it takes 855ms :

image

Both contains 29 lines with 336 points. On the update we are changing the colors of the lines.

virtualmartire commented 1 year ago

Hi, we also have a performance regression issue when migrating from 2.x.x to 4.x.x. Here is a diff when calling chart.update() on a line chart.

With 2.x.x, it takes 180ms :

image

With 4.x.x, it takes 855ms :

image

Both contains 29 lines with 336 points. On the update we are changing the colors of the lines.

@bertrandp have you solved your problem? I am exactly in the same situation 😩

bertrandp commented 1 year ago

@bertrandp have you solved your problem? I am exactly in the same situation 😩

No. Currently we have both versions in our app (v2 and v4) because in some place the regression is too important, this is annoying. @virtualmartire can you open a new issue and mention my previous message ? Maybe it will be more visible ...

virtualmartire commented 1 year ago

No. Currently we have both versions in our app (v2 and v4) because in some place the regression is too important, this is annoying. @virtualmartire can you open a new issue and mention my previous message ? Maybe it will be more visible ...

Sorry but I don't have the time to prepare all the documentation they request for a simple issue :(

ashley-mort commented 8 months ago

I also tried to update from 2.9.4 to 3.9.1 or 4.4.1 and both versions were slower. Way slower when using Chrome with Devtools open which is 90% of my workday. We ended up staying on 2.9.4.

bertrandp commented 5 months ago

Any updates on this ? Hopefully this will be fixed in v5

vmlb13 commented 5 months ago

Same issue here, angular 17, with chart js version 4.4.1. When loading 5 pie charts in a specific lazy loaded component the charts works fine in terms of interaction, but when I leave the component all the other buttons, links and page become very slow to open and render

mebibou commented 3 months ago

I am facing the exact same issue, and was wondering if I migrated incorrectly or if version > 2 had poor performance. Now I know I have to revert all the changes I made and keep using version 2.9 instead. Would be great to focus on this for next version, as performance is pretty critical for a UI library

mcmelhem commented 2 months ago

Any updates on this issue? we are facing the problem when updating the charts with new data. The whole page freeze where scrolling and clicking button becomes laggy. Our charts show more than 10k points.

FlorysiakSimon commented 1 week ago

Same issue when rendering multiple charts with 1500+ points on the same page even with parsing & animation set to false. Still looking for fixes