Performance issue; how to analyse the code's performance / find the bottleneck?

Hello there,
On a PC, my app currently needs 2-4sec to fully refresh the figures.
On an iPhone 6S, it takes around 15 sec.
On an iPad 2, it takes 40sec to load 20% of the data, but then it crashes, and the page is reloaded, to crash again, etc.

So, I was wondering if there is a smart way to find what callbacks are the most time-consuming. Without a clear understanding of what takes time and what doesn’t, it’s quite hard to know how to improve the app.

A few things to consider: the devices listed differ in two regards: the PC is probably connected via ethernet while the other two are on Wi-Fi, and the PC is probably much better off in terms of computational power. Also, if the PC you’re using is the same where the app is hosted, then it is obviously faster. Also, something weird might be going on with browser caches, so check that out too.

That said, you can overwrite the app.callback to include a timer / logger. Maybe that could help. Another way would be to try to use a load generator (e.g.

Example code (this may fail though: there is probability that you will need another level of nesting for the app.callback):

def my_decorator(cb):
    def inner(*args, **kwargs):
        start = time.time()
        result =  cb(*args, **kwargs)
        end = time.time()
        save(start, end, result)  # some save func
     return inner

app.callback = my_decorator(app.callback)

Thanks @kmouratidis for your reply, but you can disregard the 2 biases you mention;

  • The app is running on a VPS ( If I open the console and check the performance tab, it shows on average 4sec of scripting to display the default page.
  • My PC, iPhone, and iPad are all on the same node on my network, that is, connected on WiFi

For sure the CPU of my iPad 2 is old, but still, the fact that my app needs more than 30sec to be rendered is a bit weird. OpenGL issue coming from the 3D scatter plot? If I load more than 10 models (tab “by Model”) then Safari crashes…

Beats me. Did you try timing with the decorator method, or something else? If you found a solution in these past 2 weeks I am really interested. I haven’t gotten around implementing this for my app yet (or even tested on mobile devices) and I’m curious for future reference.

I will keep you posted, but for the time being I’m working on the automatisation of my crawlers, parsers, data cleansers, aggregators, which must run in the background. I aim to provide daily stats :slight_smile:

If I manage to find the cause of the bottleneck, I will let you know. I’m not yet familiar enough with what a “decorator method” is, sorry for this, but I will investigate :slight_smile:

In the current version, one callback loads the data, then generates the 3 graph. As a consequence, the 3 figures are displayed only after they are ready.

On a local version of this app, I changed this; I know have 3 callback triggered at the same time when I click on one particular tab. Data are therefore loaded 3 times simultaneously. In theory, the 3 figures can now be displayed as soon as each one is ready.

The thing is…it didnt change any thing to the scripting time, or maybe something like 80ms…but in the wrong direction hahaha…

My guess right now is that maybe the way I’ve avoided some circular dependencies might be the cause of some inefficiencies…(when you click on a brand name, it fills the dcc.dropdown with the models names, and if you remove one of the model, it update the style of the brand (button))

I will start investigating deeper in the second part of the month and I will let you know.

1 Like

Did you check for duplication of computation or data traffic? I’m asking because this seems weird:

How big is the codebase? If it’s not too large, I could take a quick look.

1 Like

The callback generating the 2D figures in each of the 5 scenarii (5tabs) is 800 lines long,
The callback generating the 3D figures in each of the 5 scenarii (5tabs) is 300 lines long,
The callback generating the pie figures in each of the 5 scenarii (5tabs) is 200 lines long,
There is around 2500 lines of callbacks related to the styles.

The data loaded is quite small ; 1.2MB per file, and total 3 files.

I will try to remove all the callbacks handling the styling steps…

I guess that if I proceed this way, soon or later I will find where the problem is

Thank you for the help proposal, but I think I will keep digging for a while on my side first, prior to using your time :slight_smile:

Are you running it on the built-in flask server or a WSGI?

On the VPS, it’s running with GUnicorn & NGINX.