Benchmark des performances de thread léger utilisant async / await implémenté dans Python 3.5

Depuis que async / await a été ajouté dans Python 3.5, j'ai essayé de le comparer en termes de consommation de mémoire et de coût de changement de contexte.

Quelle est la syntaxe async / await?

Il s'agit de la syntaxe la plus avancée du paradigme de traitement asynchrone qui vous permet d'écrire de manière agréable un traitement asynchrone et un traitement d'E / S non bloquant. Après avoir été implémenté en C #, il a été implémenté en C ++, VB, Node.js et est finalement arrivé à Python! C'est comme ça. La fonctionnalité est que le traitement asynchrone, qui a été écrit en dur dans Threading, peut être écrit de manière plus concise et plus puissante. Les threads légers sont également appelés microthreads ou fibres, et sont une solution au problème que les performances matérielles ne peuvent pas être pleinement utilisées lorsqu'il y a de nombreux clients en raison d'une attente d'E / S appelée «problème C10K» (problème de 10 000 clients). C'est un. En changeant le contexte à grande vitesse en attendant les E / S et en manipulant d'autres clients, vous serez en mesure d'écrire des programmes qui font ressortir les performances du matériel à la limite. En d'autres termes, si vous le maîtrisez, vous pourrez écrire un serveur qui fonctionne à haute vitesse et léger comme nginx.

Résultats de référence

Les résultats du benchmark sont que le collout utilisant async / await de Python a démarré rapidement, consommé moins de mémoire et a eu un changement de contexte rapide. N'est-ce pas une implémentation que l'on peut appeler un thread léger? Selon le «livre Wow Erlang», le fil léger d'Erlamg commence par 4 Ko de consommation de mémoire en microsecondes. La version Python consomme 3,44 Ko de mémoire et démarre à 60 microsecondes, ce qui est comparable à Erlang.

article valeur
Heures de début et de fin pour 100 000 collouts 6.081sec
Heure de début et de fin par collout 0.0608ms
Temps d'exécution de 1 million de commutateurs de contexte 51.435sec
Temps d'exécution par changement de contexte 51.435μs
Consommation de mémoire lors du démarrage de 100 000 collouts 146.86MByte
Consommation de mémoire par collout 1.50KByte
Consommation de mémoire lorsque 100000 collouts sont démarrés et que le changement de contexte est exécuté 1 million de fois 336.30MByte
Consommation de mémoire par unité lorsque le changement de contexte est exécuté 1 million de fois 3.44KByte

Traitement pour lequel Python async / await convient

Traitement pour effectuer plusieurs E / S réseau et E / S fichier de manière asynchrone

Essayez async / wait

Ecrire un FizzBuzz régulier

Fizz Buzz ordinaire


def fizzbuzz(i):
    if i == 15:
        return 'FizzBuzz'
    if i % 5 == 0:
        return 'Buzz'
    if i % 3 == 0:
        return 'Fizz'
    return str(i)


for x in range(1, 10):
    print(fizzbuzz(x))

FizzBuzz avec un collout avec async / await

Le résultat sera le même car il ne fonctionne que dans la corroutine. スクリーンショット 2015-11-03 18.59.47.png

1 collout


import asyncio
async def main():
    await task_fizzbuzz()


async def task_fizzbuzz():
    for x in range(1, 10):
        print(fizzbuzz(x))
    return None

loop = asyncio.get_event_loop()
#Appelez la fonction principale dans le collout
loop.run_until_complete(main())
loop.close()

Async / await exécute 100000 collouts de FizzBuzz de manière asynchrone

Générez 100 000 collouts et exécutez-les en même temps. Lorsqu'une coroutine termine son exécution, le contexte change et la coroutine suivante est exécutée. スクリーンショット 2015-11-03 18.52.02.png

Corroutine 100 000 exécutions simultanées


# -*- coding: utf-8 -*-
# from asyncio import Queue
# from queue import Queue
import asyncio

async def task_fizzbuzz(prefix):
    for x in range(1, 10):
        # await asyncio.sleep(1)
        print(prefix + "{}:".format(str(x)) + fizzbuzz(x))
    return None

loop = asyncio.get_event_loop()
#Générer 100 000 collouts
tasks = asyncio.wait([task_fizzbuzz(str(i) + ":") for i in range(1, 100000)])
loop.run_until_complete(tasks)
loop.close()

100000 résultats d'exécution corroutine


....
71798:7:7
71798:8:8
71798:9:Fizz
84034:1:1
84034:2:2
84034:3:Fizz
84034:4:4
84034:5:Buzz
84034:6:Fizz
84034:7:7
84034:8:8
84034:9:Fizz
17235:1:1
17235:2:2
....

Async / await s'exécute de manière asynchrone avec 100000 collouts FizzBuzz avec sommeil

Ceci est un test pour voir si le contexte bascule avec succès lors de la mise en veille pendant la logique fizzbuzz.

100000 exécutions simultanées de collouts avec sommeil


# -*- coding: utf-8 -*-
# from asyncio import Queue
# from queue import Queue
import asyncio

async def task_fizzbuzz(prefix):
    for x in range(1, 10):
        await asyncio.sleep(1) #Code nouvellement ajouté
        print(prefix + "{}:".format(str(x)) + fizzbuzz(x))
    return None

loop = asyncio.get_event_loop()
#Générer 100 000 collouts
tasks = asyncio.wait([task_fizzbuzz(str(i) + ":") for i in range(1, 100000)])
#Exécution parallèle
loop.run_until_complete(tasks)
loop.close()

Résultat d'exécution de 100000 coroutines avec sommeil


....
75219:6:Fizz
8282:6:Fizz
57464:6:Fizz
75220:6:Fizz
8283:6:Fizz
57465:6:Fizz
75221:6:Fizz
8284:6:Fizz
57466:6:Fizz
75222:6:Fizz
8285:6:Fizz
57467:6:Fizz
75223:6:Fizz
....

Si vous dormez avec ʻawait asyncio.sleep (1) `pendant que la coroutine est en cours d'exécution, vous obtenez le résultat qu'elle s'exécute en même temps car elle passe à une autre coroutine. スクリーンショット 2015-11-03 19.25.56.png

Prenez une référence

Maintenant que la vérification est terminée, nous allons prendre le benchmark avec les trois programmes suivants.

  1. Un programme qui exécute FizzBuzz 10 fois x 100 000 fois sans utiliser de collouts
  2. Un programme qui lance 100 000 collouts et exécute FizzBuzz 10 fois x 100 000 fois
  3. Un programme qui exécute FizzBuzz 10 fois x 100 000 fois en lançant 100 000 collouts et en exécutant Sleep pour chaque FizzBuzz pour exécuter un total de 1 million de changements de contexte.

スクリーンショット 2015-11-03 19.46.41.png

1. Pas de collout

# -*- coding: utf-8 -*-
import time

def fizzbuzz(i):
    if i == 15:
        return 'FizzBuzz'
    if i % 5 == 0:
        return 'Buzz'
    if i % 3 == 0:
        return 'Fizz'
    return str(i)

COUNT = 100000
FIZZBUZZ_COUNT = 10

#Commencer la mesure
ts = time.time()

#10 fois FizzBuzz x 100000 fois
for x in range(COUNT):
    for x in range(FIZZBUZZ_COUNT):
        print(fizzbuzz(x))
#Attendez 10 secondes pour que la condition soit la même que les autres
for x in range(FIZZBUZZ_COUNT):
    time.sleep(1)

#Fin de la mesure
te = time.time()

#Sortie de résultat
print("{}sec".format(te-ts))


2. Lancez 100 000 collouts

# -*- coding: utf-8 -*-
import time
import asyncio

def fizzbuzz(i):
    if i == 15:
        return 'FizzBuzz'
    if i % 5 == 0:
        return 'Buzz'
    if i % 3 == 0:
        return 'Fizz'
    return str(i)

COUNT = 100000
FIZZBUZZ_COUNT = 10

#Commencer la mesure
ts = time.time()

#10 fois FizzBuzz x 100000 fois
async def task_fizzbuzz(prefix):
    for x in range(FIZZBUZZ_COUNT):
        # await asyncio.sleep(1)
        print(prefix + "{}:".format(str(x)) + fizzbuzz(x))
    return None

loop = asyncio.get_event_loop()
tasks = asyncio.wait([task_fizzbuzz(str(i) + ":") for i in range(COUNT)])
loop.run_until_complete(tasks)
loop.close()

#Attendez 10 secondes pour que la condition soit la même que les autres
for x in range(FIZZBUZZ_COUNT):
    time.sleep(1)

#Fin de la mesure
te = time.time()

#Sortie de résultat
print("{}sec".format(te-ts))

3. Lancez 100 000 collouts Changement de contexte 1 million de fois

# -*- coding: utf-8 -*-
import time
import asyncio

def fizzbuzz(i):
    if i == 15:
        return 'FizzBuzz'
    if i % 5 == 0:
        return 'Buzz'
    if i % 3 == 0:
        return 'Fizz'
    return str(i)

COUNT = 100000
FIZZBUZZ_COUNT = 10

#Commencer la mesure
ts = time.time()

#10 fois FizzBuzz x 100000 fois
async def task_fizzbuzz(prefix):
    for x in range(FIZZBUZZ_COUNT):
        await asyncio.sleep(1)
        print(prefix + "{}:".format(str(x)) + fizzbuzz(x))
    return None

loop = asyncio.get_event_loop()
tasks = asyncio.wait([task_fizzbuzz(str(i) + ":") for i in range(COUNT)])
loop.run_until_complete(tasks)
loop.close()

#Fin de la mesure
te = time.time()

#Sortie de résultat
print("{}sec".format(te-ts))

Résultats de référence

Je ne le fais que 3 fois chacun. Le changement de contexte prend trop de temps (›´ω`‹) Je ne l'ai pas écrit pour garder les résultats simples, mais Benchmark 2 semble avoir eu lieu 100 000 changements de contexte.

スクリーンショット 2015-11-03 19.58.15.png

スクリーンショット 2015-11-03 19.50.43.png

référence

PEP 0492 -- Coroutines with async and await syntax 18.5.3. Tâches et collaborateurs 18.5.9. Develop with asyncio Nouveautés de Python 3.5 How to use async/await in Python 3.5? Programmation asynchrone avec Async et Await (C # et Visual Basic) (https://msdn.microsoft.com/en-us/library/hh191443.aspx) AsyncIO vs Gevent? : Python - Reddit

Recommended Posts

Benchmark des performances de thread léger utilisant async / await implémenté dans Python 3.5
Scraping à l'aide de Python 3.5 async / await
Masquer les websockets async / attendent dans Python3
Implémentation de SimRank en Python
python async / attend curio
Implémentation de Shiritori en Python
Convertir l'API asynchrone de style callback en async / await en Python
Scraping à l'aide de la syntaxe Python 3.5 Async
Exécutez LINE Bot implémenté en Python (Flask) "sans utiliser Heroku"
Implémentation de Supreme Solver dans Python 3
Traduit à l'aide de googletrans en Python
Utilisation du mode Python dans le traitement
Programmation GUI en Python avec Appjar
Précautions lors de l'utilisation de Pit avec Python
Implémentation de la segmentation d'image en python (Union-Find)
Essayez d'utiliser LevelDB avec Python (plyvel)
Règles d'apprentissage Widrow-Hoff implémentées en Python
Implémentation de la méthode de propagation d'étiquettes en Python
[Python] Requête asynchrone avec async / await
Utilisation de variables globales dans les fonctions python
Voyons voir l'utilisation de l'entrée en python
Puissance totale en Python (en utilisant functools)
Implémentation des règles d'apprentissage Perceptron en Python
Reconnaissance de caractères manuscrits à l'aide de KNN en Python
Essayez d'utiliser LeapMotion avec Python
Implémenté en 1 minute! LINE Notify en Python
Recherche de priorité de profondeur à l'aide de la pile en Python
Lors de l'utilisation d'expressions régulières en Python
Création d'interface graphique en python avec tkinter 2
Fonctionnement de la souris à l'aide de l'API Windows en Python
Notes utilisant cChardet et python3-chardet dans Python 3.3.1.
Essayez d'utiliser l'API Wunderlist en Python
Création d'interface graphique en python à l'aide de tkinter partie 1
Un client HTTP simple implémenté en Python
Obtenir l'équilibre Suica en Python (en utilisant libpafe)
Pratique d'utilisation de ceci en Python (mauvais)
Hachez lentement les mots de passe en utilisant bcrypt en Python
Essayez d'utiliser l'API Kraken avec Python
Utilisation de venv dans un environnement Windows + Docker [Python]
Grande différence dans les performances de ruby, python, httpd
Implémenté en Python PRML Chapitre 7 SVM non linéaire
[FX] Hit oanda-API avec Python en utilisant Docker
Tweet à l'aide de l'API Twitter en Python
[Python] [Windows] Communication série en Python à l'aide de DLL
J'ai essayé d'utiliser l'optimisation bayésienne de Python
Connectez-vous à Slack à l'aide de requêtes en Python
Obtenez des données Youtube en Python à l'aide de l'API Youtube Data
J'ai essayé d'implémenter la régression logistique de Cousera en Python
Utilisation des constantes physiques dans Python scipy.constants ~ constant e ~
Scraping de sites Web à l'aide de JavaScript en Python
Développement de slack bot avec python en utilisant chat.postMessage
Ecrire un module python dans fortran en utilisant f2py
Dessinez une structure arborescente en Python 3 à l'aide de graphviz
Implémenté dans Python PRML Chapter 5 Neural Network
Remarques sur l'utilisation de python (pydev) avec eclipse
Classification des maladies par Random Forest en utilisant Python
Mise en œuvre du tri Stuge dans Python 3 (tri à bulles et tri rapide)
Implémenté en Python PRML Chapitre 1 Estimation bayésienne
Téléchargez des fichiers dans n'importe quel format en utilisant Python