<a id="about-launchpad-performance"></a>

# About Launchpad performance

This document provides an overview of techniques and tools that can help
Launchpad developers run Launchpad more efficiently - faster, and using fewer
system resources.

## Measure, don’t guess

In order to ensure highly performant web services, we need to have a look at
numbers.

We conduct regular performance checks with Google’s [PageSpeed Insights](https://pagespeed.web.dev/) for
which we currently score an excellent 98 out of 100 for desktop browsers, with
intentions to close the last bits.

We also have [internal monitoring](https://grafana.admin.canonical.com/d/oIhMaXhMk/launchpad-dash?orgId=1&refresh=5m) set up with Grafana, where we measure and
monitor various metrics.

## Timeouts

It is important to have sensible timeouts, as otherwise very slow clients could
block resources for too long, and prevent other clients from connecting.

We use a default of 5 seconds for all page views. This value can be tweaked on
a per page level via [feature rules](https://launchpad.net/+feature-rules).

## Writing performant Python code

As a general guideline, writing clean and modern Python code usually produces
reasonably fast code.

As a base, you need to [choose the correct data structure](https://www.pythonmorsels.com/time-complexities/), depending on
whether you optimize for lookups, appending elements, or similar.

You also should be aware of the [runtime complexity (Big O)](https://en.wikipedia.org/wiki/Big_O_notation) of your code.

Another way to ensure high performance is to use caches. Caches are usually
used to avoid repeated expensive calculations and database lookups.
While Launchpad uses caches on various levels, you should be aware of the
`propertycache` module, which offers a `cachedproperty` decorator.
For more information please refer to its [documentation](https://git.launchpad.net/launchpad/tree/lib/lp/services/doc/propertycache.rst).

It is also recommended to run the latest version of a software, as that one is
usually the fastest one.
This applies both to third party Python libraries, and also to the
[Python interpreter](https://devblogs.microsoft.com/python/python-311-faster-cpython-team/) itself.

## Debugging and optimizing database issues

Many performance issues are typically caused by inefficient database queries.

In order to prevent issues in the first place you should be aware of how to
[write efficient queries](https://dev.launchpad.net/Database/Performance).

You should also make use of the already mentioned `cachedproperty` decorator
in order to avoid querying the database more often then necessary.

When changing code, it can easily happen to increase the query count. You can
avoid this by using a helper to
[preserve query count](https://ubuntu.com/docs/launchpad/developer/how-to/launchpad-development-tips/preserve-query-count/index.html.md#preserve-query-count).

When you face performance or even timeout issues, you should learn more about
[timeout analysis](https://drive.google.com/file/d/1hUivL07Msoyej3wd_T4hMAX61EJzfE38/view?usp=drive_link) (internal video).

PostGreSQL comes with a [builtin tool](https://www.postgresql.org/docs/current/sql-explain.html) to analyze SQL queries.

## Delivering payload

We leverage various ways to improve performance on the server side.

Apache is configured to make use of the gzip compression.

Also static files, such as CSS and JavaScript, are directly served by
[Apache](https://git.launchpad.net/launchpad/tree/charm), instead of the application server, which reduces CPU load and
enables more effective caching.

We also use various helpers to combine and compress JavaScript and CSS files
before delivery. Launchpad’s [Makefile](https://git.launchpad.net/launchpad/tree/Makefile) is a good place to start
investigating until there is documentation available.
