By defaut, SQLAlchemy uses lazy loading, which means that displaying n
bills will generate around n queries (to get the list of owers of each
bill). Pre-load the list of owers to drastically decrease the number of
SQL queries.
Before this commit: 1004 SQL queries, 7535 ms elapsed time, 7536 ms CPU time, 530 ms SQL time
After this commit: 5 SQL queries, 3342 ms elapsed time, 3393 ms CPU time, 15 ms SQL time
Measured request: display the list of all bills for the project (without displaying the sidebar with balances)
Test setup to measure performance improvement:
- 5 users with various weights
- 1000 bills, each paid by a random user, each involving all 5 users
- laptop with Celeron N2830@2.16 GHz, SSD Samsung 850 EVO
- sqlite database on SSD, using sqlite 3.15.2
- python 2.7.13
- Flask-DebugToolbar 0.10.0 (to count SQL queries and loading time)
Performance measurements (using Flask-DebugToolbar with the second
request, to avoid measuring cold-cache performance):
- number of SQL queries
- elapsed time (from request to response)
- total CPU time consumed by the server handling the request
- total time spent on SQL queries (as reported by SQLAlchemy)
The only translation so far is french, but more can be added. The browser language
is used thanks to the HTTP languages headers.
There are still some problems with the translation of some strings, I don't know
why this is. See #12
- Send an email to the user with the summary of the created project
containing a reminder of the identifier, password and a link.
- Add flash message with the identifier in the /invite page/
- Add a small note containing the identifier in the upper right corner
of the project main page.
- Do not display anymore the identifier field in home.
- Let the user enter the id if the slug generated from project name already exists as a project id.
- Moved get_billform_for from 'utils' to 'forms', to avoid issue (was 'from forms import ...' into utils,
and 'from utils import ...' into forms, which causeed an error).
This is mainly because 301 is cacheable whereas 303 (See other) isn't.
The redirect response given by the app when trying to connect to a project
(via /project_name) while not authenticated was to permanently redirect to
/authenticate.
Once authenticated, the browser was redirected to the /project_name, that was
cached, leading to an endless loop.
303 see other allows to solve this problem.