perf(calendar_event): calcul des occurrences limité à la plage demandée - #65
Open
AntTBD wants to merge 3 commits into
Open
perf(calendar_event): calcul des occurrences limité à la plage demandée#65AntTBD wants to merge 3 commits into
AntTBD wants to merge 3 commits into
Conversation
…emandée calculOccurrence() itérait depuis la 1ère occurrence de l'évènement : un agenda quotidien créé en 2017 effectuait ~3000 tours de boucle à chaque rendu de widget, et un agenda horaire plusieurs dizaines de milliers. Les dashboards comportant plusieurs widgets agenda devenaient sensiblement lents. On avance d'un multiple entier de la fréquence de répétition jusqu'au dernier cycle se terminant avant $_startDate : la grille des occurrences est strictement identique à celle produite par itération. Limité aux unités de durée fixe (minutes, heures, jours, semaines), l'arithmétique PHP sur les mois n'étant pas associative en fin de mois (31 janvier +1 mois +1 mois != 31 janvier +2 mois) ; les mois et les années continuent d'itérer, le nombre de tours y étant déjà faible. Le saut est divisé par deux jusqu'à ne plus ignorer que des occurrences se terminant avant la plage, et abandonné s'il n'y parvient pas. Sortie également des invariants de la boucle : $excludeDate est indexé par clé pour un test isset() en O(1) au lieu d'un in_array(), et la vérification de until est résolue une seule fois avant la boucle au lieu d'appeler strtotime() à chaque itération.
…ence
getNationalDay() était appelée sous la forme getNationalDay(date('Y'), strtotime($startDate)), avec un second argument que la méthode n'accepte pas et l'année courante au lieu de celle de l'occurrence. Les options « sauf jours fériés » et « seulement les jours fériés » étaient donc fausses pour toute occurrence au-delà de l'année suivante.
On passe l'année de l'occurrence, et le résultat est mis en cache par année : easter_date() et 20 appels à mktime() étaient recalculés à chaque itération.
…s warnings PHP 8 Limitation de la boucle de calcul des occurrences à MAX_OCCURRENCE_LOOP itérations, avec un log de debug, afin qu'un évènement mal configuré ne puisse plus figer le rendu du widget. Ajout des tests isset() manquants sur $repeat['excludeDay'][...] et $repeat['freq'].
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
calculOccurrence()itérait depuis la 1ère occurrence de l'évènement, quelle que soit la plage demandée : des milliers de tours de boucle inutiles à chaque rendu de widget pour un agenda ancien.La boucle démarre maintenant directement au début de la plage, en avançant d'un multiple entier de la fréquence de répétition — la grille des occurrences reste donc inchangée. Limité aux unités de durée fixe (minutes, heures, jours, semaines), l'arithmétique PHP sur les mois n'étant pas associative en fin de mois.
Deux correctifs adjacents, dans des commits séparés :
getNationalDay()recevait un argument de trop et l'année courante au lieu de celle de l'occurrence : les options "jours fériés" étaient fausses au-delà de l'année suivante. Résultat mis en cache par année au passage.isset()manquants (warnings PHP 8).Comment tester. Sur
beta, exporter toutes les occurrences et le temps de calcul :Puis avec cette PR appliquée, la même commande vers
occ_apres.txt:Comparer :
IDENTIQUEattendu, hors évènements "jours fériés" au-delà de l'année suivante (2ème commit). Le gain est d'autant plus net que la plage est courte : sur ±7 jours, celle du rendu de widget, remplacer-6 months/+6 monthspar-7 days/+7 days.Suggested changelog entry
EN: Occurrences are now calculated only over the requested date range
FR: Les occurrences sont désormais calculées uniquement sur la plage de dates demandée
Related issues/external references
Fait suite à #53, réécrite sur la version actuelle de
beta.Types of changes
PR checklist