Singed, un profileur frontal pour les applications Ruby et Rails

May 09 2023
Vous êtes-vous déjà retrouvé à vouloir comprendre pourquoi un bloc de code Ruby, une requête Web particulière ou une certaine action du contrôleur fonctionnait si lentement ? Peut-être avez-vous déjà utilisé des outils de profilage tels que speedscope, mais que vous les avez trouvés encombrants, ou que vous avez essayé mais que vous n'avez pas réussi à comprendre comment les utiliser. Présentation de Singed, une nouvelle interface de profilage de Gusto écrite par Josh Nichols (alias @technicalpickles).

Vous êtes-vous déjà retrouvé à vouloir comprendre pourquoi un bloc de code Ruby, une requête Web particulière ou une certaine action du contrôleur fonctionnait si lentement ? Peut-être avez-vous déjà utilisé des outils de profilage tels que speedscope, mais que vous les avez trouvés encombrants, ou que vous avez essayé mais que vous n'avez pas réussi à comprendre comment les utiliser.

flamegraph : N'importe quoi… et c'est tout !

Présentation de Singed , une nouvelle interface de profilage de Gusto écrite par Josh Nichols (alias @technicalpickles) . Singed a été conçu pour être une interface de couteau suisse pour plusieurs outils ( stackprof , rbspy et speedscope ), vous aidant à capturer et à visualiser facilement des flamegraphs, là où auparavant vous deviez écrire un tas de passe-partout ou de code temporaire juste pour commencer .

Pourquoi un autre outil de profilage ?

Singed ajoute une nouvelle méthode sur Kernel, disponible partout :

flamegraph {
  # your code here
}

Principalement, la plupart des développeurs Ruby qui souhaitent étudier les flamegraphs utilisent rack-mini-profiler , qui est une interface excellente et facile à utiliser pour stackprof . Ajoutez simplement ?pp=flamegraph à la fin de n'importe quelle URL et whiz-bang, vous avez un flamegraph ouvert dans votre navigateur.

Cependant, nous voulons souvent profiler des choses qui ne sont pas seulement l'URL actuelle dans la barre de navigation de notre navigateur.

Par exemple, nous pouvons souhaiter profiler une requête GraphQL, qui est effectuée via une passerelle comme Apollo. Nous ne pourrons peut-être pas trouver facilement l'URL qu'Apollo Gateway utilise pour faire sa demande, il est donc difficile de répliquer et d'utiliser rack-mini-profiler pour capturer un flamegraph.

Ou, nous pourrions simplement vouloir profiler un bloc de code Ruby ou un travail d'arrière-plan, ou même un test. Vous pouvez écrire votre propre code pour ce faire et appeler vous-même stackprof, mais il s'agit de quelques dizaines de lignes passe-partout pour rediriger la sortie vers un fichier, et vous devrez probablement encore l'ouvrir manuellement dans votre navigateur.

Pourquoi utiliser Speedscope, Stackprof et rbspy ?

Singed est essentiellement un wrapper autour de trois outils différents :

  • Speedscope , un visualiseur de flamegraph.
  • stackprof , un profileur d'échantillonnage pour Ruby.
  • rbspy , un autre profileur d'échantillonnage pour Ruby, écrit en Rust.
Le visualiseur de Speedscope est beau et assez rapide, même sur de grands profils.

stackprof est un profileur d'échantillonnage pour Ruby. C'est une extension C pour la machine virtuelle Ruby, ce qui signifie qu'elle doit être "démarrée" avec votre processus Ruby en même temps. rbspy fonctionne différemment - il utilise en fait les privilèges sudo pour lire la mémoire du processus Ruby de l'extérieur. En tant que tel, il peut être attaché à tout moment à un processus Ruby, c'est pourquoi Singed l'utilise pour profiler les processus Ruby à partir de la CLI.

Les profileurs d'échantillonnage comme stackprof et rbspy sont un excellent choix car ils s'adaptent assez bien à des bases de code plus importantes. Les profileurs de traçage, comme ruby-prof , ont tendance à échouer à l'échelle de Gusto en raison des énormes quantités de code impliquées dans l'exécution de notre application.

Enfin, stackprof et rbspy bénéficient d'un grand soutien dans la communauté. Nous n'avons pas à faire notre propre mise à niveau du profileur pour prendre en charge les nouvelles versions de Ruby, par exemple.

Présentation rapide des fonctionnalités

Jetons un coup d'œil à ce que Singed peut réellement faire. L'une de mes façons préférées d'utiliser Singed consiste à profiler un simple bloc de code dans notre application Rails.

Par exemple, supposons que je veuille profiler un travail d'arrière-plan, MyWorker. Je créerais un fichier appelé myprofile.rb, le placerais dans la racine de notre application Rails, puis ajouterais :

user = User.first
flamegraph { MyWorker.new.perform(user) }

bin/rails runner myprofile.rb

Une autre chose courante que je rencontre avec les profils est qu'il est parfois assez compliqué de configurer l'état requis pour profiler un morceau de code. Peut-être que vous avez juste besoin d'un état de base de données très spécifique ou que beaucoup de code doit être exécuté en premier. Souvent, cette configuration existe déjà dans nos tests.

Singed facilite vraiment le profilage d'un test. Cela signifie que vous pouvez, bien sûr, profiler et optimiser votre suite de tests, mais je trouve vraiment cela plus utile pour profiler du code qui nécessite beaucoup de configuration particulière :

require 'singed/rspec'
RSpec.describe YourClass do
  it "is slow :(", flamegraph: true do
    # your code here
  end
end

Un autre cas d'utilisation de Singed est le profilage des demandes. Chez Gusto, nous avons une passerelle GraphQL (Apollo) qui fait des requêtes à notre backend Rails. Parfois, je veux profiler ces requêtes, mais c'est assez difficile de le faire avec rack-mini-profiler car je ne connais pas l'URL et le corps de la requête que le backend Apollo envoie à Rails. Au lieu de cela, avec Singed, ce que je fais, c'est :

  • Déclenchez la requête backend GraphQL depuis le frontend.
  • Dans Chrome DevTools, je copie cette demande "as fetch". Cela me permet de le coller dans ma console Javascript et de déclencher cette requête GraphQL à la demande.
  • J'arrête et redémarre mon serveur principal, cette fois en ajoutant la variable d'environnement SINGED_MIDDLEWARE_ALWAYS_CAPTURE=1.
  • Je relance la requête dans ma console Javascript.

Vous pouvez également facilement profiler un démarrage d'application Rails :

bundle binstub singed
bin/singed -- bin/rails runner 'true'

Une interface de profileur avec de nombreuses utilisations

J'espère vous avoir convaincu d'essayer Singed. Je l'utilise presque quotidiennement chez Gusto.

Si vous avez trouvé cela intéressant, consultez-le sur GitHub .