User story
J'utilise profile de python et j'aimerais ne voir que les fonctions appelées dans un fichier et sortir les graphs correspondants.
Et accessoirement, t'as envie de montrer comment yahi peut s'utiliser pour d'autres graphs que les analyses de pages web.
Résultat
Le résultat est ici sous forme de page web
Le chemin
Patcher profile
D'abord, il faut commencer à patcher profile de la stdlib pour sortir les données sous forme d'un log « regexpable » :
+++ mprofile/__init__.py 2026-05-24 09:24:37.185491502 +0200
@@ -330,6 +330,7 @@
callers[pfn] = 1
timings[rfn] = cc, ns - 1, tt + rit, ct, callers
+ print(f"{time.time()} {rfn} {rit} {ct} {pfn}")
return 1
NB : je n'ai absolument pas compris ce que je renvoyais comme données.
Pour moi :
rfn = fonction appelée
rit = temps passé dans le frame où la fonction est appelée
ct = temps passé dans le frame parent (?????)
pfn = fonction appelante
Écrire un script spécifique à yahi
Ensuite après avoir récupéré les journaux d'un profilage, il faut écrire un script de sélection des données.
Ici ; on ne souhaite qu'inclure les entrées dont le chemin vers le fichier qui contient la fonction contient archery.
#!/usr/bin/env python
from yahi import notch, shoot
from json import dumps
from archery import mdict
date_formater= lambda dt :"%s-%02d-%02d %02d-%02d-%02d.%02d" % (
dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.microsecond
)
######################## Setting UP ##################################
# parsing command line & default settings. Return a not fully qualified object
context=notch(
log_format="custom",
off="geo_ip,user_agent",
output_format="json",
# ne sélectionner que les fonction dans le fichier archery/trait.py
include='''{ "from_callee" : ".*archery/trait.py" }''',
date_pattern="%s",
# datetime en format timestamp (spécifique à yahi)
log_pattern="""^(?P<datetime>\S+)\s
\('(?P<from_callee>[^']+)',\s
(?P<lineno_callee>[^']+),\s
'(?P<callee>[^']+)'\)\s
(?P<time>\S+)\s
(?P<ctime>\S+)\s
\('(?P<from_caller>[^']+)',\s
(?P<lineno_caller>[^']+),\s
'(?P<caller>[^']+)'\)$""")
# log sample
# 1779465928.7602208 ('<frozen importlib._bootstrap>', 911, '_load_unlocked') 1 1.267900000000155e-05 0.0015263490000001073 ('<frozen importlib._bootstrap>', 1304, '_find_and_load_unlocked')
##### OKAY, now we can do the job ##########################################
context.output_file.write(
dumps(
shoot(
context,
lambda data : mdict({
'date_calls':
mdict({ date_formater(data["_datetime"])
: float(data["time"]) }),
"by_overhead_callee" : mdict({ data["callee"]: float(data["ctime"]) }),
"by_overhead_caller" : mdict({ data["caller"]: float(data["ctime"]) }),
"by_time_callee" : mdict({ data["callee"]: float(data["time"]) }),
"by_time_caller" : mdict({ data["caller"]: float(data["time"]) }),
'by_callee': mdict({ data["callee"] : 1 }),
'by_caller': mdict({ data["caller"] : 1 }),
'by_transition' : mdict({ "%(caller)s=>%(callee)s" % data : 1 }),
'by_transition_time' :
mdict({ "%(caller)s=>%(callee)s" % data : float(data["ctime"]) }),
'total_line' : 1,
}),
),
indent=4
)
)
Ensuite une petite invocation de yahi suffit
python mprofile.py < ../mprofile.log > data.js && yahi_all_in_one_maker && firefox aio.html
Conclusion
Ben, j'ai été le premier surpris par la simplicité de l'exercice, et j'ai trouvé ça gratifiant.
Yahi est peut être utile pour faire de l'aggrégation de données. :)

# Contexte
Posté par Benoît Sibaud (site web personnel) . Évalué à 5 (+2/-0).
# Temps mesurés
Posté par Benoît Sibaud (site web personnel) . Évalué à 4 (+1/-0).
Si je comprends bien:
Vu de B(), parent time=1 (c'est A()), current time=2 et subfunctions/external time=6 (deux fois C()).
[^] # Re: Temps mesurés
Posté par Jul (site web personnel) . Évalué à 1 (+0/-0).
C'est donc bien le temps passé dans la fonction parente que j'ai marquée de ????? ?
Ça me rassure.
J'aurais dû faire comme toi et tester avec des fonctions simples. Mais j'étais trop dans l'envie de partager mes graphs et je m'ai précipité :)
Envoyer un commentaire
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.