123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- <!doctype html>
- <html lang=fr>
- <head>
- <!-- Always define the charset before the title -->
- <meta charset=utf-8>
- <title>Benchmarks map, filter vs. list-comprehensions — Biologeek — David Larlet</title>
- <!-- Define a viewport to mobile devices to use - telling the browser to assume that the page is as wide as the device (width=device-width) and setting the initial page zoom level to be 1 (initial-scale=1.0) -->
- <meta name="viewport" content="width=device-width, initial-scale=1"/>
- <!-- Fake favicon, to avoid extra request to the server -->
- <link rel="icon" href="data:;base64,iVBORw0KGgo=">
- <link type="application/atom+xml" rel="alternate" title="Feed" href="/david/log/" />
- <link rel="manifest" href="/manifest.json">
-
- <link rel="stylesheet" href="/static/david/css/larlet-david-_J6Rv.css" data-instant-track />
-
- <noscript>
- <style type="text/css">
- /* Otherwise fonts are loaded by JS for faster initial rendering. See scripts at the bottom. */
- body {
- font-family: 'EquityTextB', serif;
- }
- h1, h2, h3, h4, h5, h6, time, nav a, nav a:link, nav a:visited {
- font-family: 'EquityCapsB', sans-serif;
- font-variant: normal;
- }
- </style>
- </noscript>
-
- <!-- Canonical URL for SEO purposes -->
- <link rel="canonical" href="https://larlet.fr/david/biologeek/archives/20061025-benchmarks-map-filter-vs-list-comprehensions">
-
- </head>
- <body>
- <div>
-
- <header>
- <nav>
- <p>
- <small>
- Je suis <a href="/david/" title="Profil public">David Larlet</a>, <a href="/david/pro/" title="Activité professionnelle">artisan</a> du web qui vous <a href="/david/pro/accompagnement/" title="Activité d’accompagnement">accompagne</a><span class="more-infos"> dans l’acquisition de savoirs pour concevoir des <a href="/david/pro/produits-essentiels/" title="Qu’est-ce qu’un produit essentiel ?">produits essentiels</a></span>. <span class="more-more-infos">Discutons ensemble d’une <a href="/david/pro/devis/" title="En savoir plus">non-demande de devis</a>.</span> Je partage ici mes <a href="/david/blog/" title="Expériences bienveillantes">réflexions</a> et <a href="/david/correspondances/2017/" title="Lettres hebdomadaires">correspondances</a>.
- </small>
- </p>
- </nav>
- </header>
-
-
- <section>
- <h1 property="schema:name">Benchmarks map, filter vs. list-comprehensions</h1>
- <article typeof="schema:BlogPosting">
- <div property="schema:articleBody">
- <img src="/static/david/biologeek/images/logos/seb_sauvage.png" alt="vignette" style="float:left; margin: 0.5em 1em;" property="schema:thumbnailUrl" />
- <p>Je viens de tomber sur les <a href="http://sebsauvage.net/python/snyppets/">snyppets de Seb Sauvage</a> (site que j'apprécie beaucoup par ailleurs) et il y a une phrase qui m'a interpellé sur le <a href="http://sebsauvage.net/python/snyppets/#zip_filter_map">paragraphe consacré à zip, map, filter et aux list-comprehensions</a> :</p>
-
- <blockquote><p>Except that {map|filter} is <strong>faster</strong>. (than list-comprehensions)</p></blockquote>
-
- <p>Ni une, ni deux, je récupère l'<a href="http://programmation-python.org/sections/blog/2006_10_05_article-sur-code">article de Tarek</a> qui est très bon et qui comporte une fonction testant la durée d'execution des fonctions pour pouvoir comparer. J'avais <a href="https://larlet.fr/david/biologeek/archives/20060121-bonnes-pratiques-de-la-programmation-en-python/">déjà essayé d'autres fonctions</a> mais autant innover un peu.</p>
-
- <p>Allons-y donc avec le décorateur suivant :</p>
-
- <pre>from test import pystone
- import time
-
- kPs = 1000
- TOLERANCE = 0.5 * kPs
-
- def mesure_pystone():
- pystone.pystones(loops=pystone.LOOPS)
- pystone.pystones(loops=pystone.LOOPS)
- return pystone.pystones(loops=pystone.LOOPS)
-
- def timedtest(function, local_pystones=mesure_pystone()):
- """ Decorator to measure execution time in pystones """
- def wrapper(*args, **kw):
- all = []
- for i in range(3):
- start_time = time.time()
- try:
- res = function(*args, **kw)
- finally:
- total_time = time.time() - start_time
- if total_time == 0:
- temps = 0
- else:
- ratio = local_pystones[0] / local_pystones[1]
- temps = total_time / ratio
- all.append(temps)
- print '%d pystones' % min(all)
- return res
- return wrapper</pre>
-
- <p>J'ai testé les fonctions suivantes qui ne sont pas les mêmes que les exemples de Seb mais qui retournent (elles, <a href="http://www.haypocalc.com/blog/">merci Haypo</a> :-)) le même résultat :</p>
-
- <pre>@timedtest
- def map_without_list_comprehension():
- for i in range(10000):
- map(abs, [-5,7,-12])
-
- @timedtest
- def map_with_list_comprehension():
- for i in range(10000):
- [abs(i) for i in [-5,7,-12]]
-
- print '=== map vs. list-comprehension ==='
- print 'map without list-comprehension:'
- map_without_list_comprehension()
- print 'map with list-comprehension:'
- map_with_list_comprehension()
-
- @timedtest
- def filter_without_list_comprehension():
- for i in range(10000):
- filter(abs, [-5,7,0,-12] )
-
- @timedtest
- def filter_with_list_comprehension():
- for i in range(10000):
- [i for i in [-5,7,0,-12] if i]
-
- print '=== filter vs. list-comprehension ==='
- print 'filter without list-comprehension:'
- filter_without_list_comprehension()
- print 'filter with list-comprehension:'
- filter_with_list_comprehension()</pre>
-
- <p>Et voila les résultats obtenus :</p>
-
- <blockquote><p>=== map vs. list-comprehension ===<br />
- map without list-comprehension:<br />
- 638 pystones<br />
- map with list-comprehension:<br />
- 534 pystones<br />
- === filter vs. list-comprehension ===<br />
- filter without list-comprehension:<br />
- 612 pystones<br />
- filter with list-comprehension:<br />
- 550 pystones<br /></p></blockquote>
-
- <p>Il me semble que c'est sans appel : les list-comprehensions sont <strong>toujours</strong> plus rapides que map ou filter avec Python 2.4. Il faudrait tester tout ça avec Python 2.5 mais je pense que les résultats seraient encore plus significatifs.</p>
- </div>
- </article>
- <footer>
- <h6 property="schema:datePublished">— 25/10/2006</h6>
- </footer>
- </section>
- <section>
- <div>
- <h3>Articles peut-être en rapport</h3>
- <ul>
- <li><a href="/david/biologeek/archives/20080511-bonnes-pratiques-et-astuces-python/" title="Accès à Bonnes pratiques et astuces Python">Bonnes pratiques et astuces Python</a></li>
- <li><a href="/david/biologeek/archives/20060425-python-et-underscore/" title="Accès à Python : lisibilité vs simplicité">Python : lisibilité vs simplicité</a></li>
- <li><a href="/david/biologeek/archives/20060304-principales-nouveautes-dans-python-25/" title="Accès à Principales nouveautés dans Python 2.5">Principales nouveautés dans Python 2.5</a></li>
- </ul>
- </div>
- </section>
- <section>
- <div id="comments">
- <h3>Commentaires</h3>
-
- <div class="comment" typeof="schema:UserComments">
- <p class="comment-meta">
- <span class="comment-author" property="schema:creator">Tarek</span> le <span class="comment-date" property="schema:commentTime">26/10/2006</span> :
- </p>
- <div class="comment-content" property="schema:commentText">
- <p>Le même script sous Python 2.5 :<br />
- <br />
- tziade@dabox:~$ python test2.py<br />
- === map vs. list-comprehension ===<br />
- map without list-comprehension:<br />
- 707 pystones<br />
- map with list-comprehension:<br />
- 634 pystones<br />
- === filter vs. list-comprehension ===<br />
- filter without list-comprehension:<br />
- 687 pystones<br />
- filter with list-comprehension:<br />
- 634 pystones</p>
- </div>
- </div>
- <div class="comment" typeof="schema:UserComments">
- <p class="comment-meta">
- <span class="comment-author" property="schema:creator">JS</span> le <span class="comment-date" property="schema:commentTime">26/10/2006</span> :
- </p>
- <div class="comment-content" property="schema:commentText">
- <p>Bon, j'ai rien compris au map et list-comprehension, faudrait que je regarde ca de plus près...<br />
- <br />
- Par contre, t'es sur #python-fr ???</p>
- </div>
- </div>
- <div class="comment" typeof="schema:UserComments">
- <p class="comment-meta">
- <span class="comment-author" property="schema:creator">sebsauvage</span> le <span class="comment-date" property="schema:commentTime">01/12/2006</span> :
- </p>
- <div class="comment-content" property="schema:commentText">
- <p>Hello !<br />
- <br />
- Tu as oublié qu'avec de si petites données de test, l'overhead d'appel aux fonction devient non négligeable.<br />
- <br />
- J'ai refait les tests avec de plus grands ensembles de données et je maintien ce que j'ai dit:<br />
- map et filter sont plus rapide que list comprehension (sauf quand on combine map et filter).<br />
- <br />
- Voici le fichier de test:<br />
- <a href="http://sebsauvage.net/python/snyppets/maptest.py" title="http://sebsauvage.net/python/snyppets/maptest.py" rel="nofollow">sebsauvage.net/python/sny...</a><br />
- <br />
- Et les résultats:<br />
- ===== map_without_list_comprehension =====<br />
- 105 function calls in 0.231 CPU seconds<br />
- ===== map_with_list_comprehension =====<br />
- 1000005 function calls in 6.941 CPU seconds<br />
- <br />
- ===== filter_without_list_comprehension =====<br />
- 105 function calls in 0.074 CPU seconds<br />
- ===== filter_with_list_comprehension =====<br />
- 1000005 function calls in 6.889 CPU seconds<br />
- <br />
- C'est sans appel: map et filter sont nettement plus rapides.<br />
- (Dans notre exemple: d'un facteur x30 pour map, et d'un facteur x93 pour filter)<br />
- <br />
- <br />
- ...sauf quand on doit les combiner:<br />
- ===== mapfilter_without_list_comprehension =====<br />
- 2042605 function calls in 13.935 CPU seconds<br />
- ===== mapfilter_with_list_comprehension =====<br />
- 521205 function calls in 3.795 CPU seconds<br />
- <br />
- Là la list comprehension est plus rapide.<br />
- <br />
- <br />
- Donc je ne me suis pas trompé, mais c'est à mitiger. :-)<br />
- Il vaut mieux profiler le code.<br />
- </p>
- </div>
- </div>
- <div class="comment" typeof="schema:UserComments">
- <p class="comment-meta">
- <span class="comment-author" property="schema:creator">xfeeder</span> le <span class="comment-date" property="schema:commentTime">29/06/2010</span> :
- </p>
- <div class="comment-content" property="schema:commentText">
- <p>les list-comprehensions sont toujours plus rapides que map ou filter avec Python 2.4.</p>
- </div>
- </div>
-
- </div>
- </section>
-
-
- <footer>
- <nav>
- <p>
- <small>
- Je réponds quasiment toujours aux <a href="mailto:david%40larlet.fr" title="Envoyer un email">emails</a> (<a href="/david/signature/" title="Ma signature actuelle avec possibilité de chiffrement">signés</a>) et vous pouvez me rencontrer à Montréal. <span class="more-infos">N’hésitez pas à <a href="/david/log/" title="Être tenu informé des mises à jour">vous abonner</a> pour être tenu informé des publications récentes.</span>
- </small>
- </p>
- </nav>
- </footer>
-
- </div>
-
- <script src="/static/david/js/larlet-david-3ee43f.js" data-no-instant></script>
-
- <script data-no-instant>InstantClick.init()</script>
-
- </body>
- </html>
|