Dans le cadre de l'optimisation des temps de recherche des matchs, ci-dessous un ensemble de points notable qui peuvent avoir une influence sur la performance globale.
L'application wayzup-matcher
est constitué en partie d'un ensemble de workers
avec une converture de test faible.
- account_created_worker.rb
- account_deleted_worker.rb
- account_updated_worker.rb
- administrator_created_worker.rb
- administrator_deleted_worker.rb
- administrator_updated_worker.rb
- favorite_ride_regenerate_matchings_worker.rb
- favorite_trip_upsert_worker.rb
- regenerate_offers_for_mate_worker.rb
- send_ttin_worker.rb
Il existe deux types de workers, le premier groupe est en charge de syncroniser
les ressources Mate
et Administrator
qui sont présentes dans deux applicatifs
wayzup-api
et wayzup-matcher
.
Le déclenchement de la mise à jour d'une ressource doit si j'ai bien compris n'être
démarré que par les événements suivants create
, update
, delete
depuis l'application
wayzup-api
.
La suppression d'un Mate
dans le job account_deleted_worker.rb
supprime aussi
un ensemble de ressource, Le FavoriteTrip
, les FavoriteRide
, tous les
FavoriteRidesMatching
dans lequel le Mate
est passager ou conducteur.
La MAJ d'un Mate
va déclencher le recalcul des offres Offer
si son commute_mode
(moyen de déplacement) change. Une désactivation (status = :inactive) des FavoriteRidesMatching concernant
ce Mate
et lance le déclenchement d'un job MateOffersUpdatedWorker
une fois
les opérations finies.
Cette ressource ne permet que l'accès à un segment de l'API
/admin_v1
du Matcher. Les workers n'ont pas d'impact sur les autres entités du système.
Le job favorite_trip_upsert_worker.rb
à pour but de créer ou mettre à jour le
trajet d'un utilisateur Mate
, puis de regenerer les offres. L'execution de
celui-ci vient mettre en file deux nouveaux jobs dans l'applicatif wqyzup-api
- MateOffersUpdateWorker
- MateFavoriteTripUpdateWorker
Le lancement des 2 jobs afin de déterminer les Matchs FavoriteRideRegenerateMatchingsWorker
constitue 80% du temps d'execution, 5% sur l'appel du Garbage collector
Comme il est possible de voir sur ce rapport newrelic. Ce worker déclenche des appels sur OSRM avec des temps de réponses en moyenne de 15ms à 20ms ayant pour cause latence du réseau pour une part qui semble non négligeable. 14% du taux d'execution est passé sur la communication avec ce service.
En suite c'est 20% du temps d'execution qui passé sur les SELECT et INSERT desressources de type FavoriteRidesMatching
la table SQL comprends plus de 150_000 enregistements dont 50_000 avec le statut 'inactive'.
Avec un RELEVANT_RIDE_SHARING_RATIO_THRESOLD de 0.45, il y a 60_000 FavoriteRidesMatching.relevant
mais 25_000 Matchs relevant et inactif FavoriteRidesMatching.where(status: 'inactive').relevant.count
. Il y a donc en base 23% de Matchs qui peuvent battir une offre concréte.
Il y a environ 600 FavoriteRide dont la distance est supérieure à 300 kilométres soit environ 3 heures de voiture, plus ou moins un Paris-Dijon
[3] pry(main)> Sidekiq::VERSION
=> "3.5.4"
Dans l'article optimizing sidekiq Mike Perham explique les améliorations qu'il apporte sur la version
de Sidekiq 4
on peut voir une net amélioration de latence d'execution d'un job de 22ms à 10ms ainsi qu'une gestion plus fine du Garbage collector celui-ci ayayant un impact fort lors des purges sur le temps d'execution d'un job.
> $ Benchmark.measure
From: /Users/chussenot/.rbenv/versions/2.3.1/lib/ruby/2.3.0/benchmark.rb @ line 291:
Owner: #<Class:Benchmark>
Visibility: public
Number of lines: 11
def measure(label = "") # :yield:
t0, r0 = Process.times, Process.clock_gettime(Process::CLOCK_MONOTONIC)
yield
t1, r1 = Process.times, Process.clock_gettime(Process::CLOCK_MONOTONIC)
Benchmark::Tms.new(t1.utime - t0.utime,
t1.stime - t0.stime,
t1.cutime - t0.cutime,
t1.cstime - t0.cstime,
r1 - r0,
label)
end
[6] pry(main)> Benchmark.measure do Benchmark.measure {} end
=> #<Benchmark::Tms:0x007f82e263b318 @cstime=0.0, @cutime=0.0, @label="", @real=2.7899997803615406e-05, @stime=0.0, @total=0.0, @utime=0.0>
Même si l'impact reste faible sur l'execution d'une opération je ne conseille pas de garder ce type de chose pour un code en production, de plus il est souhaitable de réduire les écritures des logs au minimum et de ne pas mettre le log level sur INFO en production (Il ne pas possible de vérifier pour l'instant) mais sur le staging celui-ci est sur info LOG_LEVEL=info
Le middleware est actif dans l'environnement de :development mais le endpoint
http://localhost:3003/newrelic
n'est pas monté cf. newrelic.yml
Mettre en place celui-ci va permettre de d'inspecter les requettes SQL les plus lentes ainsi que les différents temps d'execution des fonctions avant de déployer sur le staging o la production.
Le cache dalli, n'est pas actif en staging et production c'est donc le cache
de base avec écriture dans le dossier ./tmp
qui est effectué.