{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["# Tech - profiling\n", "\n", "Le [profilage de code](https://fr.wikipedia.org/wiki/Profilage_de_code) ou *profiling* en anglais signifie qu'on mesure le temps pass\u00e9 dans chaque partie d'un programme pour en d\u00e9couvrir les parties les plus co\u00fbteuses et les am\u00e9liorer. On souhaite toujours acc\u00e9l\u00e9rer un programme trop lent, le profiling permet de savoir sur quelles parties se concentrer."]}, {"cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [{"data": {"text/html": ["
run previous cell, wait for 2 seconds
\n", ""], "text/plain": [""]}, "execution_count": 2, "metadata": {}, "output_type": "execute_result"}], "source": ["from jyquickhelper import add_notebook_menu\n", "add_notebook_menu()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Autre lecture : [Exemple de profiling](http://www.xavierdupre.fr/app/ensae_teaching_cs/helpsphinx/notebooks/profiling_example.html#profilingexamplerst)."]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Enonc\u00e9\n", "\n", "On applique le profiling au code suivant pour d\u00e9couvrir laquelle de ces fonctions est la plus lente. Vous pouvez changer ce code pour un de ceux que vous avez \u00e9crits pr\u00e9c\u00e9demment."]}, {"cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [{"data": {"text/plain": ["(0.5, 0.9)"]}, "execution_count": 3, "metadata": {}, "output_type": "execute_result"}], "source": ["def _gini_sort(Y):\n", " return list(sorted(Y))\n", "\n", "\n", "def _gini_init(Y):\n", " return [[1, y] for y in Y]\n", "\n", "\n", "def _gini_cumsum(couples):\n", " for i in range(1, len(couples)):\n", " couples[i][0] += couples[i-1][0]\n", " couples[i][1] += couples[i-1][1]\n", " for i in range(0, len(couples)):\n", " couples[i][0] /= couples[-1][0]\n", " couples[i][1] /= couples[-1][1]\n", " return couples\n", "\n", " \n", "def _gini_final(couples):\n", " g = couples[0][0] * couples[0][1]\n", " n = len(couples)\n", "\n", " for i in range(1, n):\n", " dx = couples[i][0] - couples[i-1][0]\n", " y = couples[i-1][1] + couples[i][1]\n", " g += dx * y\n", "\n", " return 1. - g / 2\n", "\n", "\n", "def gini(Y):\n", " Y = _gini_sort(Y)\n", " couples = _gini_init(Y)\n", " couples = _gini_cumsum(couples)\n", " return _gini_final(couples)\n", "\n", "\n", "gini([1, 1, 1, 1, 1]), gini([0, 0, 0, 0, 100000])"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Pour ces deux exemples caract\u00e9ristiques, on retrouve bien des valeurs attendues."]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 1 : profiler le code pr\u00e9c\u00e9dent\n", "\n", "Le langage python dispose d'un module qui mesure le temps pass\u00e9 dans chaque fonction [profile](https://docs.python.org/3/library/profile.html). Il faut l'utiliser."]}, {"cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 2 : changer la fonction _gini_final si possible en plus rapide\n", "\n"]}, {"cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 3 : vous am\u00e9liorez la fonction _gini_final, profilez pour savoir de combien ?"]}, {"cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 4 : utiliser d'autres modules de profiling\n", "\n", "Si c'est possible, comme [pyinstrument](https://github.com/joerick/pyinstrument) ou [py-spy](https://github.com/benfred/py-spy). Il y a deux fa\u00e7ons de faire du profiling :\n", "\n", "* **d\u00e9terministe :** on mesure le temps pass\u00e9 dans chaque fonction, \u00e0 chaque appel, ce type de profilage n'est souvent possible que pour des langages interpr\u00e9t\u00e9s,\n", "* **statistique :** tous les centi\u00e8mes de secondes, on regarde quelle ligne de quelle fonction le programme ex\u00e9cute. On compte ensuite combien de fois la ligne ex\u00e9cut\u00e9e \u00e9tait dans une fonction pour d\u00e9terminer le temps pass\u00e9 dans chaque fonction.\n", "\n", "Les deux modules propos\u00e9s sont statistiques, le premier est d\u00e9terministe. Bien \u00e9videmment, le fait de mesurer le temps pass\u00e9 prend du temps \u00e9galement, plus on s'arr\u00eate souvant, plus l'ex\u00e9cution est ralentie."]}, {"cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 5 : la fonction _gini_cumsum contient deux boucles. Quelle est la plus rapide ?"]}, {"cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["## R\u00e9ponses"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 1 : profiler le code pr\u00e9c\u00e9dent\n", "\n", "On reprend un des exemples de cette page [The Python Profilers](https://docs.python.org/3/library/profile.html#module-cProfile)."]}, {"cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": [" 55 function calls in 0.000 seconds\n", "\n", " Ordered by: cumulative time\n", "\n", " ncalls tottime percall cumtime percall filename:lineno(function)\n", " 2 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\site-packages\\IPython\\core\\interactiveshell.py:3400(run_code)\n", " 2 0.000 0.000 0.000 0.000 {built-in method builtins.exec}\n", " 1 0.000 0.000 0.000 0.000 :8()\n", " 2 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\codeop.py:142(__call__)\n", " 2 0.000 0.000 0.000 0.000 {built-in method builtins.compile}\n", " 1 0.000 0.000 0.000 0.000 :6()\n", " 1 0.000 0.000 0.000 0.000 :31(gini)\n", " 1 0.000 0.000 0.000 0.000 :9(_gini_cumsum)\n", " 2 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\contextlib.py:242(helper)\n", " 4 0.000 0.000 0.000 0.000 {built-in method builtins.next}\n", " 2 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\contextlib.py:86(__init__)\n", " 2 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\contextlib.py:112(__enter__)\n", " 2 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\contextlib.py:121(__exit__)\n", " 1 0.000 0.000 0.000 0.000 :19(_gini_final)\n", " 4 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\site-packages\\IPython\\core\\compilerop.py:166(extra_flags)\n", " 2 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\site-packages\\IPython\\core\\hooks.py:103(__call__)\n", " 1 0.000 0.000 0.000 0.000 :1(_gini_sort)\n", " 2 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\site-packages\\traitlets\\traitlets.py:564(__get__)\n", " 1 0.000 0.000 0.000 0.000 :5(_gini_init)\n", " 2 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\site-packages\\IPython\\core\\interactiveshell.py:3338(compare)\n", " 4 0.000 0.000 0.000 0.000 {built-in method builtins.getattr}\n", " 2 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\site-packages\\traitlets\\traitlets.py:533(get)\n", " 2 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\site-packages\\IPython\\utils\\ipstruct.py:125(__getattr__)\n", " 1 0.000 0.000 0.000 0.000 {built-in method builtins.sorted}\n", " 1 0.000 0.000 0.000 0.000 :6()\n", " 2 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\site-packages\\IPython\\core\\interactiveshell.py:1278(user_global_ns)\n", " 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}\n", " 3 0.000 0.000 0.000 0.000 {built-in method builtins.len}\n", " 2 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\site-packages\\IPython\\core\\hooks.py:168(pre_run_code_hook)\n", "\n", "\n", "\n"]}], "source": ["import cProfile, pstats, io\n", "from pstats import SortKey\n", "pr = cProfile.Profile()\n", "pr.enable()\n", "\n", "gini([1, 1, 1, 1, 1])\n", "\n", "pr.disable()\n", "s = io.StringIO()\n", "sortby = SortKey.CUMULATIVE\n", "ps = pstats.Stats(pr, stream=s).sort_stats(sortby)\n", "ps.print_stats()\n", "print(s.getvalue())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Tous les temps sont nuls. Le code est trop rapide. Il faut soit ex\u00e9cuter le code plusieurs fois, soit prendre un tableau plus grand."]}, {"cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": [" 11045 function calls in 1.352 seconds\n", "\n", " Ordered by: cumulative time\n", "\n", " ncalls tottime percall cumtime percall filename:lineno(function)\n", " 2 0.000 0.000 1.352 0.676 c:\\python395_x64\\lib\\site-packages\\IPython\\core\\interactiveshell.py:3400(run_code)\n", " 2 0.000 0.000 1.352 0.676 {built-in method builtins.exec}\n", " 1 0.040 0.040 1.352 1.352 :6()\n", " 1000 0.003 0.000 1.266 0.001 :31(gini)\n", " 1000 0.706 0.001 0.707 0.001 :9(_gini_cumsum)\n", " 1000 0.357 0.000 0.357 0.000 :19(_gini_final)\n", " 1000 0.001 0.000 0.185 0.000 :5(_gini_init)\n", " 1000 0.184 0.000 0.184 0.000 :6()\n", " 1000 0.047 0.000 0.047 0.000 :7()\n", " 1000 0.005 0.000 0.013 0.000 :1(_gini_sort)\n", " 1000 0.008 0.000 0.008 0.000 {built-in method builtins.sorted}\n", " 3000 0.001 0.000 0.001 0.000 {built-in method builtins.len}\n", " 2 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\codeop.py:142(__call__)\n", " 2 0.000 0.000 0.000 0.000 {built-in method builtins.compile}\n", " 2 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\contextlib.py:242(helper)\n", " 2 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\contextlib.py:86(__init__)\n", " 4 0.000 0.000 0.000 0.000 {built-in method builtins.next}\n", " 2 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\contextlib.py:121(__exit__)\n", " 2 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\contextlib.py:112(__enter__)\n", " 4 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\site-packages\\IPython\\core\\compilerop.py:166(extra_flags)\n", " 2 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\site-packages\\IPython\\core\\hooks.py:103(__call__)\n", " 2 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\site-packages\\traitlets\\traitlets.py:564(__get__)\n", " 1 0.000 0.000 0.000 0.000 :9()\n", " 4 0.000 0.000 0.000 0.000 {built-in method builtins.getattr}\n", " 2 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\site-packages\\IPython\\core\\interactiveshell.py:3338(compare)\n", " 2 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\site-packages\\IPython\\utils\\ipstruct.py:125(__getattr__)\n", " 2 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\site-packages\\traitlets\\traitlets.py:533(get)\n", " 2 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\site-packages\\IPython\\core\\interactiveshell.py:1278(user_global_ns)\n", " 2 0.000 0.000 0.000 0.000 c:\\python395_x64\\lib\\site-packages\\IPython\\core\\hooks.py:168(pre_run_code_hook)\n", " 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}\n", "\n", "\n", "\n"]}], "source": ["import cProfile, pstats, io\n", "from pstats import SortKey\n", "pr = cProfile.Profile()\n", "pr.enable()\n", "\n", "for i in range(1000):\n", " gini([1 for i in range(1000)])\n", "\n", "pr.disable()\n", "s = io.StringIO()\n", "sortby = SortKey.CUMULATIVE\n", "ps = pstats.Stats(pr, stream=s).sort_stats(sortby)\n", "ps.print_stats()\n", "print(s.getvalue())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["C'est un peu illisible. On filtre."]}, {"cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": [" 1000 0.003 0.000 1.266 0.001 :31(gini)\n", " 1000 0.706 0.001 0.707 0.001 :9(_gini_cumsum)\n", " 1000 0.357 0.000 0.357 0.000 :19(_gini_final)\n", " 1000 0.001 0.000 0.185 0.000 :5(_gini_init)\n", " 1000 0.005 0.000 0.013 0.000 :1(_gini_sort)\n"]}], "source": ["def filtre(text):\n", " lines = text.split(\"\\n\")\n", " return \"\\n\".join(filter(lambda t: \"gini\" in t, lines))\n", "\n", "print(filtre(s.getvalue()))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 2 : changer la fonction _gini_final si possible en plus rapide"]}, {"cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [{"data": {"text/plain": ["(0.9, 0.5, 0.9, 0.5)"]}, "execution_count": 12, "metadata": {}, "output_type": "execute_result"}], "source": ["def _gini_final_faster(couples):\n", " g = couples[0][0] * couples[0][1]\n", " n = len(couples)\n", "\n", " # par construction, tous les dx sont identiques, cela fait des calculs en moins\n", " # le code suivant est plus rapide mais peut encore \u00eatre optimis\u00e9\n", " dx = couples[0][0]\n", " sy = couples[0][0]\n", " for i in range(1, n): \n", " sy = couples[i-1][1] + couples[i][1]\n", " g += dx * sy\n", "\n", " return 1. - g / 2\n", "\n", "\n", "def gini_faster(Y):\n", " Y = _gini_sort(Y)\n", " couples = _gini_init(Y)\n", " couples = _gini_cumsum(couples)\n", " return _gini_final_faster(couples)\n", "\n", "\n", "(gini_faster([0, 0, 0, 0, 5000]), gini_faster([1, 1, 1, 1, 1]),\n", " gini([0, 0, 0, 0, 5000]), gini([1, 1, 1, 1, 1]))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 3 : vous am\u00e9liorez la fonction _gini_final, profilez pour savoir de combien ?\n", "\n", "On appelle les deux fonctions pour pouvoir comparer."]}, {"cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": [" 2000 1.085 0.001 1.086 0.001 :9(_gini_cumsum)\n", " 1000 0.003 0.000 0.999 0.001 :31(gini)\n", " 1000 0.003 0.000 0.882 0.001 :16(gini_faster)\n", " 2000 0.002 0.000 0.315 0.000 :5(_gini_init)\n", " 1000 0.275 0.000 0.275 0.000 :19(_gini_final)\n", " 1000 0.174 0.000 0.175 0.000 :1(_gini_final_faster)\n", " 2000 0.009 0.000 0.024 0.000 :1(_gini_sort)\n"]}], "source": ["import cProfile, pstats, io\n", "from pstats import SortKey\n", "pr = cProfile.Profile()\n", "pr.enable()\n", "\n", "for i in range(1000):\n", " gini([1 for i in range(1000)])\n", " gini_faster([1 for i in range(1000)])\n", "\n", "pr.disable()\n", "s = io.StringIO()\n", "sortby = SortKey.CUMULATIVE\n", "ps = pstats.Stats(pr, stream=s).sort_stats(sortby)\n", "ps.print_stats()\n", "print(filtre(s.getvalue()))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["La seconde version est plus rapide."]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 4 : utiliser d'autres modules de profiling\n", "\n", "[pyinstrument](https://github.com/joerick/pyinstrument) n'est pas peut-\u00eatre pas install\u00e9. Il fonctionne de la m\u00eame fa\u00e7on."]}, {"cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [{"data": {"text/html": ["\n", " \n", " \n", " \n", " \n", " \n", "
\n", " \n", " \n", " \n", " "], "text/plain": [""]}, "execution_count": 14, "metadata": {}, "output_type": "execute_result"}], "source": ["from pyinstrument import Profiler\n", "from IPython.display import HTML\n", "\n", "profiler = Profiler()\n", "profiler.start()\n", "\n", "for i in range(1000):\n", " gini([1 for i in range(1000)])\n", " gini_faster([1 for i in range(1000)])\n", "\n", "profiler.stop()\n", "\n", "HTML(profiler.output_html())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["C'est plus facile \u00e0 lire."]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 5 : la fonction _gini_cumsum contient deux boucles. Quelle est la plus rapide ?\n", "\n", "Pour ce faire, on d\u00e9coupe la fonction en deux."]}, {"cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [{"data": {"text/plain": ["(0.5, 0.9)"]}, "execution_count": 15, "metadata": {}, "output_type": "execute_result"}], "source": ["def _gini_cumsum2a(couples):\n", " for i in range(1, len(couples)):\n", " couples[i][0] += couples[i-1][0]\n", " couples[i][1] += couples[i-1][1]\n", " return couples\n", "\n", "\n", "def _gini_cumsum2b(couples):\n", " for i in range(0, len(couples)):\n", " couples[i][0] /= couples[-1][0]\n", " couples[i][1] /= couples[-1][1]\n", " return couples\n", "\n", "\n", "def _gini_cumsum2(couples):\n", " _gini_cumsum2a(couples)\n", " _gini_cumsum2b(couples)\n", " return couples\n", "\n", "\n", "def gini2(Y):\n", " Y = _gini_sort(Y)\n", " couples = _gini_init(Y)\n", " couples = _gini_cumsum2(couples)\n", " return _gini_final(couples)\n", "\n", "\n", "gini2([1, 1, 1, 1, 1]), gini2([0, 0, 0, 0, 100000])"]}, {"cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": [" 1000 0.003 0.000 1.144 0.001 :21(gini2)\n", " 1000 0.003 0.000 1.038 0.001 :16(gini_faster)\n", " 1000 0.001 0.000 0.641 0.001 :15(_gini_cumsum2)\n", " 1000 0.637 0.001 0.638 0.001 :9(_gini_cumsum)\n", " 2000 0.002 0.000 0.341 0.000 :5(_gini_init)\n", " 1000 0.332 0.000 0.332 0.000 :19(_gini_final)\n", " 1000 0.326 0.000 0.326 0.000 :1(_gini_cumsum2a)\n", " 1000 0.314 0.000 0.314 0.000 :8(_gini_cumsum2b)\n", " 1000 0.200 0.000 0.200 0.000 :1(_gini_final_faster)\n", " 2000 0.009 0.000 0.024 0.000 :1(_gini_sort)\n"]}], "source": ["import cProfile, pstats, io\n", "from pstats import SortKey\n", "pr = cProfile.Profile()\n", "pr.enable()\n", "\n", "for i in range(1000):\n", " gini2([1 for i in range(1000)])\n", " gini_faster([1 for i in range(1000)])\n", "\n", "pr.disable()\n", "s = io.StringIO()\n", "sortby = SortKey.CUMULATIVE\n", "ps = pstats.Stats(pr, stream=s).sort_stats(sortby)\n", "ps.print_stats()\n", "print(filtre(s.getvalue()))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Elles sont aussi rapides l'une que l'autre. On peut n\u00e9anmoins en acc\u00e9l\u00e9rer une puisqu'on divise tous les \u00e9l\u00e9ments d'un tableau par une m\u00eame valeur. On peut la stocker dans une variable plut\u00f4t que d'aller la chercher \u00e0 chaque fois dans le tableau."]}, {"cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [{"data": {"text/plain": ["(0.5, 0.9)"]}, "execution_count": 17, "metadata": {}, "output_type": "execute_result"}], "source": ["def _gini_cumsum3b(couples):\n", " total0 = couples[-1][0]\n", " total1 = couples[-1][1]\n", " for i in range(0, len(couples)):\n", " couples[i][0] /= total0\n", " couples[i][1] /= total1\n", " return couples\n", "\n", "\n", "def _gini_cumsum3(couples):\n", " _gini_cumsum2a(couples)\n", " _gini_cumsum3b(couples)\n", " return couples\n", "\n", "\n", "def gini3(Y):\n", " Y = _gini_sort(Y)\n", " couples = _gini_init(Y)\n", " couples = _gini_cumsum3(couples)\n", " return _gini_final(couples)\n", "\n", "\n", "gini2([1, 1, 1, 1, 1]), gini2([0, 0, 0, 0, 100000])"]}, {"cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": [" 1000 0.002 0.000 1.002 0.001 :21(gini2)\n", " 1000 0.002 0.000 0.935 0.001 :16(gini3)\n", " 2000 0.568 0.000 0.568 0.000 :19(_gini_final)\n", " 2000 0.567 0.000 0.567 0.000 :1(_gini_cumsum2a)\n", " 1000 0.001 0.000 0.561 0.001 :15(_gini_cumsum2)\n", " 1000 0.001 0.000 0.496 0.000 :10(_gini_cumsum3)\n", " 2000 0.002 0.000 0.285 0.000 :5(_gini_init)\n", " 1000 0.275 0.000 0.275 0.000 :8(_gini_cumsum2b)\n", " 1000 0.213 0.000 0.213 0.000 :1(_gini_cumsum3b)\n", " 2000 0.008 0.000 0.022 0.000 :1(_gini_sort)\n"]}], "source": ["import cProfile, pstats, io\n", "from pstats import SortKey\n", "pr = cProfile.Profile()\n", "pr.enable()\n", "\n", "for i in range(1000):\n", " gini2([1 for i in range(1000)])\n", " gini3([1 for i in range(1000)])\n", "\n", "pr.disable()\n", "s = io.StringIO()\n", "sortby = SortKey.CUMULATIVE\n", "ps = pstats.Stats(pr, stream=s).sort_stats(sortby)\n", "ps.print_stats()\n", "print(filtre(s.getvalue()))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["C'est mieux m\u00eame si l'am\u00e9lioration ne para\u00eet pas n\u00e9cessairement significative par rapport au temps total, le r\u00e9sultat l'est si on regarde le temps fonction par fonction."]}, {"cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": []}], "metadata": {"kernelspec": {"display_name": "Python 3", "language": "python", "name": "python3"}, "language_info": {"codemirror_mode": {"name": "ipython", "version": 3}, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.5"}}, "nbformat": 4, "nbformat_minor": 2}