Profilage des gestionnaires de procédures stockées de Snowpark Python¶
Vous pouvez découvrir combien de temps ou de mémoire a été consacré à l’exécution du code de votre gestionnaire en utilisant le profileur de code intégré. Le profileur génère des informations décrivant le temps ou la mémoire consacrés à l’exécution de chaque ligne du gestionnaire de procédure.
À l’aide du profileur, vous pouvez générer des rapports axés sur l’un des éléments suivants à la fois :
Quantité de temps par ligne, dans lequel le rapport indique le nombre de fois qu’une ligne a été exécutée, la durée de l’exécution, etc.
Utilisation de la mémoire par ligne, dans lequel le rapport indique la quantité de mémoire consommée par ligne.
Le profileur enregistre le rapport généré dans la zone de préparation interne à l’utilisateur de Snowflake que vous spécifiez. Vous pouvez lire la sortie du profileur à l’aide de la fonction StoredProcedureProfiler.get_output
.
Note
Le profilage introduit une surcharge de performance lors de l’exécution de Python et peut affecter les performances de la requête. Il est destiné au développement et aux tests et ne doit pas être activé sur des charges de travail de production continue.
Privilèges requis¶
Lorsqu’une procédure stockée est exécutée après l’appel de la fonction StoredProcedureProfiler.set_active_profiler
, Snowflake vérifie les privilèges suivants pour l’utilisateur qui exécute la procédure :
Vous devez disposer de privilèges de lecture et d’écriture sur la zone de préparation de sortie du profilage.
Si la procédure stockée profilée est une procédure stockée avec droits de l’appelant, vous devez utiliser un rôle avec le privilège USAGE sur la procédure stockée.
Si la procédure stockée profilée est une procédure stockée avec droits du propriétaire, vous devez utiliser un rôle avec le privilège OWNERSHIP sur la procédure stockée.
Limitations¶
Seules les procédures stockées sont prises en charge. Les UDFs ne sont pas encore prises en charge.
Le profilage récursif n’est pas pris en charge. Seules les fonctions de premier niveau des modules spécifiés sont profilées, tandis que les fonctions définies à l’intérieur des fonctions ne le sont pas.
Le profilage des procédures stockées créées côté client via l’API
snowflake.snowpark
n’est pas pris en charge.Les fonctions Python exécutées en parallèle sur
joblib
ne sont pas profilées.Les procédures stockées définies par le système ne peuvent pas être profilées. Elles ne produisent aucune sortie.
L’API du profilage doit être utilisée dans le même thread que celui à partir duquel la procédure a été appelée.
Utilisation¶
Une fois l’ensemble des paramètres définis, vous pouvez utiliser le profileur en appelant simplement la procédure stockée pour générer la sortie du profileur. Une fois l’exécution de la procédure terminée, la sortie du profileur est écrite dans un fichier sur la zone de préparation que vous avez spécifiée. Vous pouvez récupérer la sortie du profileur à l’aide d’une fonction du système, comme décrit ci-dessous.
Suivez les étapes suivantes pour configurer et utiliser le profileur dans votre code :
Faites l’acquisition d’un objet profileur à partir de l’objet
Session
.Indiquez la zone de préparation de Snowflake dans laquelle la sortie du profil doit être écrite.
Activez le profileur et définissez le rapport de profil.
Appelez la procédure stockée.
Affichez la sortie du profilage.
Acquérir un objet de profilage¶
En Python, créez une variable de type StoredProcedureProfiler
avec laquelle vous configurerez et exécuterez le profileur.
# Create your sesssion
session = Session.builder.configs(CONNECTION_PARAMETERS).create()
# Acquire profiler object
profiler = session.stored_procedure_profiler()
Spécifiez la zone de préparation de Snowflake dans laquelle la sortie du profil doit être écrite¶
Avant d’exécuter le profileur, vous devez spécifier une zone de préparation dans laquelle enregistrer la sortie. Pour spécifier la zone de préparation, appelez StoredProcedureProfiler.set_target_stage
, en spécifiant le nom complet d’une zone de préparation interne de Snowflake dans laquelle le rapport doit être écrit.
Gardez à l’esprit les points suivants :
Le nom de la zone de préparation doit être un nom entièrement qualifié.
Si la zone de préparation que vous entrez dans cette fonctionnalité n’existe pas, Snowflake crée une zone temporaire portant ce nom.
Si vous souhaitez conserver la sortie du profileur en dehors de la session, créez une zone de préparation permanente avant d’exécuter
set_target_stage
et spécifiez le nom de cette zone permanente dans l’appel de la fonction.Si vous ne définissez pas de zone de préparation cible avec
set_target_stage
, Snowflake paramètre la zone de préparation temporaire de la session en cours comme zone cible. Pour découvrir cette zone de préparation temporaire, appelezSession.get_session_stage
.
Le code de l’exemple suivant crée une zone de préparation temporaire profiler_output
pour recevoir la sortie du profileur.
profiler.set_target_stage("mydb.myschema.profiler_output")
Activer le profileur en spécifiant son focus¶
Utilisez la fonction StoredProcedureProfiler.set_active_profiler
, en spécifiant une valeur indiquant le type de rapport de profil que vous souhaitez générer.
Pour que le profileur rende compte de l’activité d’utilisation de la ligne, définissez le paramètre sur la valeur
LINE
(insensible à la casse), comme indiqué ci-dessous :profiler.set_active_profiler("LINE")
Pour que le profileur rende compte de l’activité d’utilisation de la mémoire, définissez le paramètre sur la valeur
MEMORY
(insensible à la casse), comme indiqué ci-dessous :profiler.set_active_profiler("MEMORY")
Pour désactiver le profileur, utilisez la fonction StoredProcedureProfiler.disable
.
Appeler la procédure stockée¶
Une fois le profilage activé, appellez votre procédure stockée.
session.call("my_stored_procedure")
Voir la sortie du profilage¶
À la fin de l’exécution, vous pouvez accéder à la sortie à l’aide de la fonction StoredProcedureProfiler.get_output
.
profiler.get_output()
Inclure des modules supplémentaires pour le profilage¶
Lors du profilage, vous pouvez inclure des modules qui ne sont pas inclus par défaut.
Par défaut, les méthodes définies dans votre module sont profilées. Ces méthodes incluent ce qui suit :
La méthode du gestionnaire
Méthodes définies dans le module
Méthodes importées de paquets ou d’autres modules
Pour inclure des modules supplémentaires pour le profilage, utilisez la fonction StoredProcedureProfiler.register_modules
, en spécifiant les modules que vous souhaitez inclure.
Le code de l’exemple suivant enregistre les modules module_A et module_B pour le profilage.
profiler.register_modules(["module_A", "module_B"])
Pour annuler l’enregistrement des modules enregistrés, utilisez register_modules
sans arguments, comme dans l’exemple suivant.
profiler.register_modules()
Exemple¶
Les exemples suivants montrent comment utiliser le profileur pour générer et récupérer un rapport sur l’utilisation des lignes.
Le code de cet exemple crée une procédure profiler_test_proc
.
CREATE OR REPLACE PROCEDURE profiler_test_proc()
RETURNS NUMBER
LANGUAGE PYTHON
RUNTIME_VERSION = 3.8
PACKAGES = ('snowflake-snowpark-python')
HANDLER = 'main'
AS
$$
from snowflake.snowpark.functions import col, udf
def main(session):
df = session.sql("select 1")
return df.collect()[0][0]
$$;
Le code de l’exemple suivant établit un paramètre de profilage, puis profile la procédure profiler_test_proc
.
profiler = profiler_session.stored_procedure_profiler
profiler.register_modules(["profiler_test_proc"])
profiler.set_target_stage(
f"{db_parameters['database']}.{db_parameters['schema']}.{tmp_stage_name}"
)
profiler.set_active_profiler("LINE")
profiler_session.call("profiler_test_proc")
res = profiler.get_output()
print(res)
profiler.disable()
profiler.register_modules([])
La sortie du profil de ligne générée ressemble à ceci :
Handler Name: main
Python Runtime Version: 3.8
Modules Profiled: ['main_module']
Timer Unit: 0.001 s
Total Time: 0.0619571 s
File: _udf_code.py
Function: main at line 4
Line # Hits Time Per Hit % Time Line Contents
==============================================================
4 def main(session):
5 1 0.4 0.4 0.6 df = session.sql("select 1")
6 1 61.6 61.6 99.4 return df.collect()[0][0]