Multithreading multi-CPU Ruby

Salut, comme je l’ai mentionné dans des publications précédentes, je fais des tests de ma migration Drupal vers Discourse pour avoir toutes les solutions en place avant de désactiver l’ancien site pour migrer les données de production avec ses ~2 millions de publications. Ce que j’ai appris, c’est que sur un VPS assez rapide avec 3 cœurs de vCPU, le processus d’importation prend une éternité, environ 48 heures. Et ensuite, je devrai probablement faire un peu plus de nettoyage avec des tâches rake et/ou rails c, et pour tout ce qui nécessite un rake posts:rebake, cela prendra encore environ 20 heures.

Je ne comprends pas vraiment les bases de la chaîne d’outils Ruby. Mais si j’ajoute plus de cœurs de processeur au travail, cela réduira-t-il considérablement le temps nécessaire à l’achèvement de l’un de ces processus ? Par exemple, une commande bundle ou une commande rake pourra-t-elle diviser son travail entre les CPU disponibles, ou les cœurs supplémentaires sont-ils principalement utiles pour exécuter plusieurs processus simultanés lorsque plusieurs utilisateurs accèdent au site Web ?

1 « J'aime »

Je suis hors sujet, mais lorsque je travaillais sur une migration de forum avec le même nombre de messages, j’ai modifié le script d’importation pour importer seulement 1/100 ou 1/1000 des sujets et des messages.

C’est un moyen plus rapide de voir si votre importation est fiable et si des ajustements ou des débogages sont nécessaires.

3 « J'aime »

@Canapin En fait, merci beaucoup de l’avoir mentionné, j’aimerais vraiment savoir comment vous avez fait. J’ai voulu faire la même chose, mais j’ai abandonné l’idée car je supposais que je rencontrerais des incohérences de base de données avec une importation partielle. J’ai donc fini par créer un forum de test Drupal squelettique pour tester. Mais je préférerais tester une copie de la base de données de production.

Je suis principalement préoccupé par la migration finale de production, je devrai mettre l’ancien forum hors ligne ou du moins le rendre en lecture seule, et cela semble être au moins 48 heures d’indisponibilité au mieux, à moins que doubler les cœurs de processeur ne réduise le temps de moitié ?

1 « J'aime »

Les tâches qui prennent beaucoup de temps à restaurer sont effectivement multi-threadées. Une mise en garde est que 2 fois le nombre de CPU n’est presque jamais égal à 2 fois les performances.

Un autre point est que généralement les tâches pour rake posts:rebake et le gros du travail du forum lui-même pour récupérer et optimiser le contenu peuvent se faire avec le forum en ligne. Ce qui pourrait réduire le temps pendant lequel vous avez besoin que le forum soit hors ligne ou en lecture seule et être en mesure d’offrir une expérience quelque peu dégradée.

Ma recommandation serait : d’abord, tester. Effectuez la migration, voyez combien de temps cela prend et à quoi ressemble le forum sans tous les rebakes en place. Si le temps est suffisant, planifiez la fin de la migration autour des heures de faible trafic de votre forum, de cette façon vous gagnez environ 4 à 10 heures de migration sans que beaucoup de gens ne se plaignent.

3 « J'aime »

Excellent, merci de confirmer cela, je me posais aussi cette question.

Malheureusement, je ne l’ai pas noté et j’ai oublié… Mais si vous connaissez le codage, cela ne devrait pas être très difficile.
J’ai peut-être ajusté les valeurs de BATCH_SIZE et offset entre autres pour modifier la boucle et la faire sauter des lots de publications ou quelque chose comme ça…

Je ne peux pas réessayer maintenant car je n’ai plus de forum à importer, mais je ferai un tutoriel rapide la prochaine fois car je pense que c’est très utile.

1 « J'aime »

Je souhaite mentionner deux choses.

  • Oui, les CPU sont importants, alors procurez-vous simplement un VPS plus grand et exécutez plusieurs instances Sidekiq pour le rebaking et le traitement d’images, cela sera plus rapide.
  • Lorsque votre importation est totalement terminée, c’est toujours une bonne idée de faire une sauvegarde/restauration, cela améliorera les performances de votre base de données.

Ces deux éléments combinés : obtenez un grand VPS pour l’importation et une fois terminé, déplacez-le vers un VPS de production plus petit (en utilisant la sauvegarde et la restauration).

En général, une importation ne nécessitera pas de rebaking des publications par la suite.

3 « J'aime »

Merci beaucoup Richard pour votre réponse. Alors, lesquels parmi ceux-ci ?

  • UNICORN_WORKERS
  • UNICORN_SIDEKIQS
  • DISCOURSE_SIDEKIQ_WORKERS

Intéressant, je n’avais jamais vu cette recommandation auparavant. Est-ce que cela réduit la fragmentation ou quelque chose comme ça ?

Oui, j’allais initialement essayer de corriger certains problèmes de [QUOTE] et la conversion Textile → Markdown avec regexp_replace() dans la console Postgres, puis re-cuire toutes les publications, car les commandes rake posts:remap étaient tout simplement trop lentes. Mais j’ai ensuite découvert que la saveur regexp que Postgres utilise n’est pas compatible PCRE, et il y a trop d’anomalies inattendues pour s’y fier. Je vais donc essayer de faire passer les publications par Pandoc pendant le processus d’importation, ce qui me permettra de mettre en ligne le site importé dans un état présentable, puis de corriger les éléments plus petits comme les mots-clés d’emoji avec rake posts:remap.

  • UNICORN_SIDEKIQS – nombre de processus (par défaut 1)
  • DISCOURSE_SIDEKIQ_WORKERS – nombre de threads dans un processus (par défaut 5)

Cela réduit la fragmentation et corrige le fait que les statistiques Postgres peuvent être faussées en raison de l’importation.

2 « J'aime »

:+1:

Je n’avais jamais vu ce conseil auparavant non plus. Si c’est « toujours une bonne idée », peut-être qu’il devrait être ajouté à Pre-launch checklist after migrating from another platform ?

Je pense que c’est Sam ou Jeff qui m’a donné ce conseil il y a de nombreuses années. Je ne le trouve plus. Peut-être devrions-nous vérifier si c’est toujours une bonne idée et/ou si cela en vaut la peine :wink:

1 « J'aime »

Par hasard, quelqu’un pourrait-il me donner des conseils sur la façon la plus rapide de relancer un script d’importation et de le faire réimporter les données ? J’essaie de modifier certaines substitutions de texte dans le script d’importation, et quand je ne fais pas les bons changements, je dois supprimer la base de données Discourse et relancer ./launcher rebuild import, ce qui prend beaucoup de temps. J’aimerais apporter des modifications à mon script d’importation et le faire recommencer depuis le début (j’utilise actuellement une petite base de données squelette de mon site, donc l’exécution de l’importateur est très rapide).

Hmmm. Je teste une autre importation de mes données de forum de production, cette fois sur un VPS assez puissant avec 8 cœurs virtuels et 16 Go de RAM. J’ai défini :
UNICORN_SIDEKIQS=4
DISCOURSE_SIDEKIQ_WORKERS=20
UNICORN_WORKERS=16

Avec cela, il ne semble pas tirer parti de tous les cœurs pendant la phase import_topics :

Bien qu’il soit intéressant que le graphique CPU ait été utilisé à plus de 600 % (donc ~6 cœurs sur 8 utilisés à 100 %) pendant la phase user_import.

J’ai également remarqué cette variable d’environnement : RUBY_GLOBAL_METHOD_CACHE_SIZE=131072 serait-elle trop petite ?

Je pense que lors de l’état de création d’utilisateur, il y a plus d’actions qui sont gérées de manière asynchrone par Sidekiq.
Une grande partie de l’importation ne bénéficiera malheureusement pas de la parallélisation, vous devriez plutôt optimiser pour la vitesse du CPU monocœur.

Théoriquement, vous pourriez exécuter différents morceaux de l’importation des sujets en parallèle, mais cela nécessiterait un refactoring considérable de l’importateur et s’assurer que tout est traité dans l’ordre. Cela n’en vaut pas la peine pour une tâche unique avec quelques itérations.

2 « J'aime »

J’ai suivi une combinaison de ces deux guides [1] [2] pour importer avec un accès à un autre conteneur Docker exécutant une copie de la base de données du forum source en MySQL. Mais j’ai réalisé qu’au lieu de créer un conteneur import séparé, je peux simplement utiliser un seul conteneur app et y ajouter le mysql-dep.tempate :

templates:
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/web.template.yml"
  - "templates/web.ratelimited.template.yml"
  - "templates/web.ssl.template.yml"
  - "templates/web.letsencrypt.ssl.template.yml"
  - "templates/import/mysql-dep.template.yml"

Cela me permet d’avoir une instance Discourse fonctionnelle pendant que le script d’importation s’exécute. Y a-t-il un inconvénient à ouvrir le forum au public dès que tous les utilisateurs et catégories sont importés, et à simplement informer les utilisateurs avec une bannière qu’il faudra quelques jours avant qu’il soit entièrement peuplé ? Je pense qu’au minimum, je pourrais l’ouvrir après l’importation de tous les sujets et messages, mais avant l’importation des messages privés, car l’importation des messages privés à elle seule prendra environ 24 heures.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.