Open Tristramg opened 1 year ago
Première étape pour estimer les performances de l’asynchrone sur pg, uniquement sur l’import du railjson dans la base (pas la génération).
Le code à l’arrache est visible ici https://github.com/osrd-project/osrd/commit/9d0b52a628d015a392e8698ccb297bb391f4d76c
Les fonctions sont dupliquées pour pouvoir les tester indépendamment. Il y a trois cas testés:
Les 3 cas ont été testés avec le jeu de données de la France avec hyperfine
hyperfine --prepare 'cargo build --release' --parameter-scan async 0 2 -D 1 'cargo run --release -- --psql-port=15432 --run-async=
{async} import-railjson france ./france.railjson
'
# Asynchrone séquentiel
Benchmark 1: cargo run --release -- --psql-port=15432 --run-async=0 import-railjson france ./france.railjson
Time (mean ± σ): 24.028 s ± 1.256 s [User: 4.678 s, System: 0.618 s]
Range (min … max): 23.079 s … 27.229 s 10 runs
# Sans transaction
Benchmark 2: cargo run --release -- --psql-port=15432 --run-async=1 import-railjson france ./france.railjson
Time (mean ± σ): 15.343 s ± 3.783 s [User: 4.649 s, System: 0.601 s]
Range (min … max): 11.270 s … 21.668 s 10 runs
# Séquentiel synchrone
Benchmark 3: cargo run --release -- --psql-port=15432 --run-async=2 import-railjson france ./france.railjson
Time (mean ± σ): 29.963 s ± 3.912 s [User: 4.607 s, System: 0.432 s]
Range (min … max): 25.423 s … 37.007 s 10 runs
Il y a donc un léger gain à faire de l’asynchrone tout en restant séquentiel.
En enlevant totalement les transactions, le gain est significatif car on peut utiliser des connexions différents. Par contre, en cas de soucis, bien évidemment pas de rollback automatique.
Il semble que PG soit capable de paralléliser automatiquement avec la même connexion (permettant de garder la transaction) https://docs.rs/diesel-async/0.3.2/diesel_async/struct.AsyncPgConnection.html# mais on n’en voit pas les bénéfices ici.
Je pense que c’est lié au fait de découper la requête en plusieurs chunks
( https://github.com/osrd-project/osrd/commit/9d0b52a628d015a392e8698ccb297bb391f4d76c#diff-2dd65b6c4e3d30284b3a9058d429ad38edabbcaf448f8e52372b8c2e917c369fR88 )
Il faut encore explorer le comportement si persist_batch_async
retournait un Vec
pour faire un grand try_join_all
https://github.com/orgs/osrd-project/projects/12/views/7?pane=issue&itemId=25095490
On a big railjson, the import lasts 3:03 minutes. 1:17 is spent on importing 0:41 is spent on generating
There seems to be a low hanging fruit on: https://github.com/osrd-project/osrd/blob/dev/editoast/src/models/infra.rs#L115-L138 where all the requests are made sequentially. There is a single postgres process at 100% during the import.
If we want to parallelize the import, we need async sql (using something else than diesel?) and we might need to split the transaction (and writing rollback code by hand — but a
delete cascade
should be quite trivial).Should we accept to have two SQL connectors (diesel and sqlx ?) ? Or try to switch the whole codebase to https://github.com/weiznich/diesel_async (is would require to also change the connection pool)