URL:     https://linuxfr.org/users/jul/journaux/poc-microprofilage-en-python-avec-yahi
Title:   [POC] microprofilage en python avec yahi
Authors: Jul
Date:    2026-05-24T09:51:56+02:00
License: CC By-SA
Tags:    profilage, python et yahi
Score:   1


# 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](https://jul.github.io/cv/demo2.html?route=chrono#date_calls)

# Le chemin

## Patcher profile

D'abord, il faut commencer à patcher [profile](https://github.com/python/cpython/blob/main/Lib/profile.py) de la stdlib pour sortir les données sous forme d'un log « regexpable » : 

``` diff
+++ 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](https://github.com/jul/archery).

``` python
#!/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

``` bash
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. :)


