L'art de l'État, partie 2 : la collecte des déchets Mendix client

Passer au contenu principal

L'art de l'État, 2e partie : le mécanisme de collecte des déchets

Avant de lire ce blog, je vous recommande vivement de lire d’abord cette introduction à l’état client : L'art de l'État, 1ère partie.

Pour la deuxième partie, nous allons nous plonger dans les détails du fonctionnement de la gestion des objets dans l'état client. Nous traiterons de concepts très abstraits, je vous recommande donc de garder une boisson chaude et des collations pour le cerveau à proximité pendant que vous lisez ceci (pour des idées de gestion d'objets enivrantes, je préfère moi-même grignoter des chips).

Avis de non-responsabilité : cet article de blog s'applique à Mendix 7.23.7 ​​et 8.0. Le comportement de la récupération de place peut différer dans d'autres versions. Ce blog explique comment Mendix les applications communiquent avec l'environnement d'exécution afin que vous puissiez modéliser de meilleures applications et résoudre les problèmes d'application plus efficacement.

1. Qu’est-ce que la collecte des déchets et pourquoi est-elle nécessaire ?

Vous allez créer des objets, valider, annuler et supprimer des objets lors de la modélisation de votre application. Vous pouvez afficher ces objets dans l'interface utilisateur, les transmettre à des microflux et des nanoflux, les modifier ou les utiliser dans des widgets personnalisés. Certains des objets sur lesquels vous travaillez sont persistants, d'autres non. Les objets non persistants vivent toujours en mémoire et ne sont donc jamais enregistrés dans la base de données. Vous ne pouvez également jamais valider un nouvel objet persistant, car cela le rendrait effectivement non persistant, puisqu'il réside dans la mémoire.

Au cours d'une session utilisateur typique, un utilisateur travaille avec une application pendant des heures en visitant des dizaines de pages, créant ainsi plusieurs objets (persistants ou non persistants). Ces objets font partie de l'état du client et occupent de l'espace dans la mémoire du navigateur, ce qui peut ralentir votre application au fil du temps. Mendix développeur, vous n'avez pas besoin de supprimer tous les objets que vous créez mais que vous ne validez pas dans l'application, et votre application fonctionnera toujours sans diminution des performances. Comment est-ce possible ? Qu'est-ce que Mendix Que faire avec un objet non persistant qu'un utilisateur a créé il y a dix pages ? Qu'en est-il d'une modification apportée à un objet persistant ?

Le mécanisme de collecte des déchets est la réponse à ces questions.

Journée des ordures !
Il est temps de sortir les poubelles.

Le Mendix Le client analyse les objets et les changements d'état et les supprime s'il estime qu'ils ne sont plus nécessaires. L'objectif de ce processus est de minimiser l'état conservé en mémoire. Déterminer si un Mendix L'objet requis par une application est basé sur quelques critères que j'ai détaillés ci-dessous.

2. Quand a lieu la collecte des ordures ménagères ?

Dans mon quartier, c'est généralement le mardi matin. Mendix app, le garbage collection se produit en arrière-plan lorsque vous utilisez l'application. Il se déclenche régulièrement, analyse tous les objets et leurs changements d'état, et supprime les objets ou les modifications qu'il identifie comme n'étant plus nécessaires.

3. Puis-je voir la collecte des déchets en cours ?

Vous pouvez utiliser le raccourci d’inspection d’état (Ctrl + Alt + G) pour inspecter l'état du client et éventuellement voir le ramasse-miettes. Cependant, vous aurez besoin d'un peu de chance pour voir les objets qui sont sur le point d'être récupérés. Souvent, la collecte aura lieu avant que vous ne puissiez la voir. Ici, vous pouvez voir un objet qui sera récupéré, car le ramasse-miettes n'a pas encore démarré :

vue d'état d'un objet avant gc

Dans quelques secondes, cet objet ne sera plus visible.

Vous pouvez également activer un paramètre spécial pour voir quels objets sont supprimés lors des opérations de nettoyage des ordures. Pour ce faire, ajoutez un nouveau données, rubrique avec le logCleanupStatistics : vraipropriété à la dojoConfig objet configuré dans votre application thème/index.html fichier. Votre code devrait ressembler à ceci :

dojoConfig = {
    baseUrl: "mxclientsystem/dojo/",
    cacheBust: "{{cachebust}}",
    rtlRedirect: "index-rtl.html",
    data: {
      "logCleanupStatistics": true
    } 
};

Après avoir ajouté cette section, un message d'information sera ajouté à chaque fois que le ramassage des déchets aura lieu :

statistiques gc

Avertissement : la configuration mentionnée ci-dessus n'est pas publique et peut être modifiée ou supprimée sans préavis.

4. Comment fonctionne la collecte des déchets ?

Vous savez désormais que les objets et modifications inutiles créés ou chargés dans l'application sont supprimés de l'état client, ce qui permet à vos applications de continuer à fonctionner rapidement. Mais comment cela fonctionne-t-il ?

La réponse conceptuelle à cette question est simple : la Mendix Le client doit savoir si un objet est nécessaire à un composant à un moment donné. Dans le cas contraire, il peut le supprimer de l'état. Et comme un Mendix un objet peut faire référence à un ou plusieurs objets via des associations (ou être référencé), Mendix le client doit également garder une trace des objets dépendants.

Examinons de plus près la manière dont ces concepts fonctionnent réellement dans le Mendix client.

5. Abonnements

Mes Paiements sont essentiels pour la collecte des déchets. Le système d'abonnement est un sous-système du Mendix client, et avec lui, vous pouvez demander des notifications chaque fois que des modifications se produisent sur un Mendix objet ou ses attributs. Cela ressemble à une API simple pour les widgets personnalisés, mais en fait, le Mendix Le client utilise souvent des abonnements en interne. Voici quelques exemples d'utilisation interne :

  • Chaque fois qu'une vue de données charge un objet, elle s'abonne à l'objet chargé afin de pouvoir recevoir des notifications sur des situations spécifiques (par exemple lorsque l'objet est supprimé).
  • La plupart des widgets d'entrée dépendent des abonnements pour obtenir des mises à jour sur les objets avec lesquels ils travaillent. De cette façon, ils peuvent mettre à jour leur valeur chaque fois qu'elle a été modifiée ailleurs. Les widgets Dojo s'abonnent souvent à leurs objets manuellement. Cependant widgets enfichables n'ont pas besoin de faire cela, car leurs abonnements sont pris en charge par le Mendix client.
  • Le Mendix le client s'abonne aux objets pour des règles de visibilité et d'éditabilité conditionnelles sur la page, de sorte qu'il réévalue les conditions lorsque l'objet ou l'attribut concerné change.
  • Les widgets de texte avec paramètres s'abonnent à leurs objets. Les widgets de texte s'abonnent également à tous les objets intermédiaires si une valeur de modèle dépasse les associations, de sorte que les widgets savent qu'ils doivent se mettre à jour chaque fois que les associations changent.

Les abonnements sont traités comme des entrées par le mécanisme de récupération de place pour marquer qu'un objet abonné est nécessaire dans l'application et ne doit pas être collecté : un composant ou un widget l'utilise ou en a toujours besoin.

Le Mendix Le client s'abonne également à des objets qui ne sont pas affichés dans l'interface utilisateur à un moment donné, même sans utiliser le rappel de notification. C'est une façon d'indiquer que Mendix le client a besoin de ces objets. Voici quelques exemples d'un tel comportement :

  • Objets représentant $utilisateur actuel et $sessionactuelle sont toujours abonnés dans le Mendix client, car ils vivent aussi longtemps que les utilisateurs utilisent l'application et peuvent être nécessaires à l'application à tout moment.

    Pas de thé $sessionactuelle l'objet n'est jamais renvoyé au client pour des raisons de sécurité, mais le Mendix le client y est toujours abonné. La raison en sera expliquée ci-dessous.

  • Un microflux de source de données pour une grille de données peut renvoyer plus d'objets que la grille de données ne peut en afficher sur une seule page. Ces objets font partie de l'état du client. Mendix le client s'abonne à tous ces objets afin que le garbage collection ne les supprime pas accidentellement de l'état client.

  • Lorsqu'une page avec un paramètre est fermée, le garbage collection peut supprimer l'objet paramètre de l'état client (en supposant que cet objet ne soit plus nécessaire). Un tel paramètre de page peut être un objet non persistant, ce qui signifie que sa suppression le rend inaccessible à jamais. Mais comme un utilisateur peut revenir en arrière en utilisant le bouton Précédent du navigateur, les objets paramètres doivent être conservés dans l'état. C'est pourquoi Mendix le client s'abonne aux objets paramètres de page des cinq dernières pages : le ramasse-miettes ne les supprime donc pas.

5.1 Puis-je voir pourquoi un objet est conservé dans cet état ?

Parfois, vous pouvez voir pourquoi un certain objet est conservé dans cet état en utilisant le Ctrl + Alt + G raccourci. Dans l'exemple ci-dessous, le Artiste l'objet est abonné par des widgets sur la page actuelle. Parfois, vous pouvez voir nul entrées dans le Widgets abonnés tableau. Cela signifie qu'ils sont abonnés à partir du Mendix client en interne ou à partir d'un widget personnalisé :

État avec abonnements

Il est donc clair que les objets abonnés doivent être conservés dans cet état tant qu'ils sont abonnés.

Est-ce tout?

6. L’importance de l’accessibilité

Comme indiqué précédemment, conserver uniquement les objets abonnés n'est pas suffisant. Mendix le client doit prendre en compte les associations. Voici un exemple non persistant Mendix objet appelé Objet A à l'intérieur de l'état client :

objet une boîte

Parce qu'il n'est pas abonné, cet objet peut être supprimé de l'état lorsque le ramassage des déchets se produit.

Ajoutons un autre objet — un objet non persistant appelé Objet B:

deux boites

Les deux objets peuvent être supprimés de l’état client, car aucun d’entre eux n’a été abonné.

Maintenant, imaginez que Objet A a une association et fait référence à Objet B comme valeur :

objet boîte a pointant vers objet boîte b

Cette situation ne change rien. Les deux objets peuvent être supprimés de l'état client car aucun d'entre eux n'est abonné.

Ici Objet A est abonné à l'aide du mx.data.subscribe API (notez la lueur rouge autour Objet A):

boîte maintenant avec lueur

Dans cette situation, les deux objets doivent être conservés dans l'état. Pourquoi ?

Objet A est abonné et ne doit donc pas être collecté car le mécanisme de récupération de place ne supprime pas les objets abonnés.

Objet B n'est pas abonné, mais cela ne signifie pas qu'il peut être collecté car Objet A s'y réfère. Considérons un microflux qui accepte Objet A en tant que paramètre. À l'intérieur de ce microflux, Objet B est récupéré avec un Récupérer l'activité en utilisant le type Association Retrieve. Si le garbage collection supprime Objet B à partir de l'état, ce microflux ne pourrait pas le récupérer.

La collecte des déchets doit donc également en tenir compte et conserver Objet B dans l'état client. Cela devrait se produire pour les raisons suivantes :

  • Objet B est « accessible » depuis Objet A: ils sont associés. Une activité de récupération dans un microflux ou un nanoflux peut l'atteindre via Objet A.
  • Objet B est non persistant, ce qui signifie qu'il ne peut pas être chargé à partir de la base de données par l'activité de récupération dans un microflux. S'il s'agissait d'une entité persistante (qui est validée), un microflux pourrait la récupérer à partir de la base de données de l'application.

Ajoutons un nouvel objet au mélange. Que devrait-il se passer avec Objet C quand la collecte des ordures a-t-elle lieu ?

3 boîtes a et c pointant toutes deux vers b

Objet C doit également être conservé dans l'état, car il peut être atteint à travers Objet A -> Objet B -> Objet C.

Il est également possible que Objet A peut faire référence à deux objets différents comme valeur de la même association. Comment cela peut-il se produire ? Imaginez que Objet A est engagé auprès d'une association se référant à Objet B. Lorsque vous faites ce même point d'association Objet D sans vous engager, vous introduisez un « changement » pour cette association. Dans ce cas, Objet A connaît à la fois la valeur validée et la valeur modifiée pour la même association :

boîte a pointant vers les boîtes b et d

La collecte des déchets prend en compte ce cas et conserve les deux Objet B et Objet C dans l'état, car les deux sont accessibles depuis Objet A.

Tous les exemples ci-dessus concernent des objets non persistants. Ajoutons à cela des objets persistants. Ils sont représentés par un arrière-plan bleu clair :

de nombreuses boîtes

Voyons ce qui devrait arriver à chaque objet persistant lorsque le garbage collection se produit.

Objet B ne doivent pas être collectées pour les raisons suivantes :

  • Le (Nouveau) Le suffixe à la fin de son nom indique qu'il n'a pas encore été validé, ce qui fait que l'objet se comporte comme un objet non persistant. Il ne peut être trouvé qu'en mémoire.
  • Il a été référencé à partir de Objet A, le marquant comme « accessible ». S'il n'avait pas été référencé, le ramasse-miettes aurait pu le supprimer de l'état client.

Objet C ne doivent pas être collectées pour les raisons suivantes :

  • Le ** à la fin de son nom indique qu'il a des modifications d'attribut/association non validées. De telles modifications ne restent en mémoire que jusqu'à Objet C est soit validé, soit annulé.
  • Il a été référencé à partir de Objet A, le marquant comme « accessible ». S'il n'avait pas été référencé, le ramasse-miettes aurait pu le supprimer de l'état client.

Objet D peuvent être collectées pour les raisons suivantes :

  • C'est un objet engagé (il n'y a pas (Nouveau) suffixe).
  • Il ne contient également aucune modification (aucun ** d'après son nom).

Cela signifie que Objet D ne contient pas de valeurs d'attribut non validées et peut être trouvé dans la base de données de l'application chaque fois que cela est nécessaire. Ainsi, le mécanisme de récupération de place le supprime de l'état client, même s'il est référencé à partir de Objet A.

Objet E peut être collecté car il n'est référencé à partir d'aucun objet souscrit. Cela signifie qu'il n'est pas du tout accessible. Le nettoyage de la mémoire peut supprimer cet objet de l'état client, y compris les modifications d'attribut/association non validées. Étant donné que cet objet n'est plus accessible, il est possible de le supprimer en toute sécurité.

Dans la section précédente, nous avons mentionné que $sessionactuelle (Système.Session) est toujours abonné dans le Mendix client, mais il ne se retrouve jamais dans l'état. Vous pouvez maintenant deviner la raison : il peut y avoir des objets dans l'état qui font référence au $sessionactuelle, donc « accessibles » depuis celui-ci. C'est pourquoi ils peuvent également être conservés dans l'État.

7. Conclusion

Avec la description ci-dessus, nous pouvons résumer plus en détail le processus de collecte des déchets comme ci-dessous :

Le nettoyage des mémoires commence à partir de tous les objets abonnés dans l'état et trouve tous les objets « accessibles » via des associations en créant un graphique de dépendances. En analysant ce graphique, il décide de conserver ou de supprimer chaque objet et (s'il existe) ses modifications dans l'état du client.

7.1 Quels objets sont conservés dans l’État ?

  • Tous les objets souscrits sont conservés dans l’état.
  • Tous les objets « accessibles » à partir des objets abonnés sont conservés s’ils appartiennent à l’une de ces catégories :
    • Objets non persistants, car ils ne peuvent pas être trouvés dans la base de données.
    • Objets persistants qui sont créés mais pas encore validés, car ils ne sont pas encore dans la base de données de l'application.
    • Objets persistants qui sont validés mais contiennent des modifications, car les modifications ne sont pas encore dans la base de données, mais un microflux peut en avoir besoin.

7.2 Quels objets sont retirés de l’État ?

  • Les objets qui ne sont pas accessibles à partir des objets abonnés sont rejetés. Ces objets proviennent souvent de pages précédentes visitées par l'utilisateur.
  • Les objets qui sont toujours accessibles à partir des objets abonnés mais dont l'état est le même que celui de la base de données sont ignorés. Ce cas s'applique aux objets persistants lorsqu'ils sont validés dans la base de données et ne subissent aucune modification. Si les objets sont nécessaires, ils peuvent être chargés à partir de la base de données.

Après avoir lu les descriptions ci-dessus, vous pourriez vous sentir un peu catatonique :

gif de chaton confus

Bon, assez de descriptions. Mettons en pratique ce que vous avez appris !

8. Le jeu de la collecte des déchets

J'ai expliqué précédemment le mécanisme de récupération de place avec des graphiques. Vous allez maintenant pouvoir jouer à un jeu pour voir si vous comprenez le mécanisme. Les scénarios du jeu proviennent de nos tests unitaires internes pour le mécanisme GC. Voyons si vous pouvez deviner les bonnes réponses !

Le jeu est simple. Vous verrez ci-dessous une représentation de l'état du client et la légende est la même que ci-dessus. Voici un exemple :

boîte

Grâce au graphique, vous pouvez voir les choses suivantes à propos de Objet 1:

  • C'est une entité persistante (fond bleu)
  • Il est abonné (la lueur rouge autour de lui)
  • Il n'est pas encore enregistré dans la base de données (il a « (nouveau) » à la fin de son nom)
  • Il contient des changements. (a ** à la fin de son nom)

Vous vous posez peut-être une question après avoir vu ce cas : un « nouvel » objet peut-il subir des modifications ? C'est possible car lorsqu'un objet est créé, ses attributs conservent leur valeur « par défaut » qui peut être définie dans le modèle de domaine. Ces valeurs par défaut deviennent la valeur « validée » actuelle des attributs, et toutes les modifications qui leur sont apportées sont stockées dans l'état.

Les objets peuvent également se référencer les uns les autres via des associations :

deux boites

Ci-dessus, vous pouvez voir que Objet 1 a une association avec une valeur définie sur Objet 2. Ni le nom ni la cardinalité de l'association n'ont d'importance pour ce jeu, ils ne sont donc pas spécifiés. Cette flèche indique que Objet 2 peut être accessible avec un Récupérer l'activité dans un microflux utilisant le Association récupérer le type.

Il y a sept niveaux dans le jeu. Chaque niveau représente l'état actuel de « l'état client » avant que le ramasse-miettes ne se produise. Votre objectif est de déterminer quels objets de l'état seront conservés et quels objets seront supprimés de l'état lorsque le ramasse-miettes aura lieu. Après cela, vous pouvez cliquer sur « Afficher les réponses » pour révéler les résultats. Vous pouvez ensuite passer au niveau suivant.

Que le jeu commence!


J'espère que vous avez apprécié le jeu ! Maintenant que vous comprenez comment Mendix le client nettoie l'état, voici quelques indices pour modéliser de meilleures applications tout en gardant à l'esprit le ramasse-miettes.

9. Bonnes pratiques : garder à l'esprit le ramassage des déchets lors de la modélisation

9.1 Ne renvoyez pas trop d'objets à partir des sources de données

Imaginez une vue de liste avec une source de microflow qui renvoie des milliers d'objets. Tous ces objets sont conservés dans l'état, alors qu'une vue de liste ne peut en afficher qu'une petite partie à un moment donné en fonction de la configuration de la pagination. Ce cas est également vrai pour une source de données nanoflow et une source de données d'association. Au lieu de cette approche, essayez d'utiliser XPath ou une source de données de base de données, qui est hautement optimisée pour les grands ensembles de données. Elle charge uniquement les données qui peuvent être affichées sur la page actuelle.

9.2 Diviser les grandes entités en entités plus petites

Travailler avec des objets volumineux augmente la taille de l'état de votre application. Un objet volumineux entier est stocké en mémoire même s'il n'a subi qu'une seule modification ou s'il n'est abonné qu'à l'un de ses attributs. Le fractionnement de ces objets peut être bénéfique pour la collecte des déchets, en particulier pour les objets non persistants. De cette façon, l'algorithme de collecte des déchets peut supprimer les objets plus petits inutilisés s'ils remplissent les conditions mentionnées ci-dessus.

9.3 Ne créez pas d’« objets étoiles »

Un « objet étoile » est un objet auquel on fait référence parmi des centaines d’autres objets. Par exemple, si vous avez un Résultat de la recherche objet, et il y en a 500 Élément de résultat de recherche s'y référant, Résultat de la recherche devient un objet vedette. S'il y a des abonnements pour l'un ou l'autre Résultat de la recherche Ou l'un des Élément de résultat de recherche objets, tous les objets peuvent être conservés dans l'état. Ce modèle est souvent un problème si tous les objets ne sont pas persistants ou contiennent des modifications.

Si vous devez travailler avec de tels objets, assurez-vous de les valider ou de les supprimer manuellement, ou de définir les valeurs des associations sur un objet étoile pour vide après les avoir utilisés.

9.4 Vérifiez la taille de l'État pendant le développement

Utilisez le bouton  Ctrl + Alt + G Raccourci pour vérifier la taille de l'état. La vérification du contenu de l'état est particulièrement importante lorsque vous travaillez avec de grandes pages. Par exemple, vous pouvez voir qu'un objet persiste là parce que vous avez oublié de vous désabonner de celui-ci dans votre widget personnalisé.

9.5 Vérifier les journaux d'exécution pour détecter les états excessifs

Le Mendix Le client envoie les parties requises de l'état aux requêtes d'exécution et un avertissement est enregistré si le nombre d'objets envoyés par le client dépasse un certain seuil. Si vous voyez un tel avertissement, vous devez revoir cette page et rechercher pourquoi il y a autant d'objets conservés dans l'état.

J'espère que vous avez apprécié la lecture de cet article et que vous le trouverez utile. Si vous avez des commentaires, des questions ou des éloges généraux 😉 contactez-moi ici.

Choisissez votre langue