Leichter Thread-Leistungsbenchmark mit async / await, implementiert in Python 3.5

Da async / await in Python 3.5 hinzugefügt wurde, habe ich versucht, es hinsichtlich des Speicherverbrauchs und der Kosten für den Kontextwechsel zu vergleichen.

Was ist die Async / Wait-Syntax?

Dies ist die fortschrittlichste Syntax im Paradigma der asynchronen Verarbeitung, mit der Sie die asynchrone Verarbeitung und die nicht blockierende E / A-Verarbeitung auf nette Weise schreiben können. Nach der Implementierung in C # wurde es in C ++, VB, Node.js implementiert und kam schließlich zu Python! Es ist wie es ist. Das Merkmal ist, dass die asynchrone Verarbeitung, die in Threading hart geschrieben wurde, präziser und leistungsfähiger geschrieben werden kann. Leichte Threads werden auch als Mikrothreads oder Fasern bezeichnet und sind eine Lösung für das Problem, dass die Hardwareleistung bei vielen Clients aufgrund von E / A-Wartezeiten, die als "C10K-Problem" bezeichnet werden (Problem von 10.000 Clients), nicht vollständig genutzt werden kann. Es ist eins. Wenn Sie den Kontext mit hoher Geschwindigkeit wechseln, während Sie auf E / A warten und andere Clients verarbeiten, können Sie Programme schreiben, die die Leistung der Hardware an ihre Grenzen bringen. Mit anderen Worten, wenn Sie es beherrschen, können Sie einen Server schreiben, der mit hoher Geschwindigkeit und geringem Gewicht wie Nginx arbeitet.

Benchmark-Ergebnisse

Das Ergebnis des Benchmarks war, dass das Collout mit Pythons async / await schnell gestartet wurde, weniger Speicher verbrauchte und einen schnellen Kontextwechsel hatte. Ist es nicht eine Implementierung, die als Lightweight-Thread bezeichnet werden kann? Laut dem "Wow Erlang Book" beginnt Erlamgs leichter Thread mit einem Speicherverbrauch von 4 KByte in Mikrosekunden. Die Python-Version verbraucht 3,44 KByte Speicher und beginnt bei 60 Mikrosekunden, was mit Erlang vergleichbar ist.

Artikel Wert
Start- und Endzeiten für 100.000 Collouts 6.081sec
Start- und Endzeit pro Collout 0.0608ms
Ausführungszeit von 1 Million Kontextwechseln 51.435sec
Ausführungszeit pro Kontextwechsel 51.435μs
Speicherverbrauch beim Starten von 100.000 Collouts 146.86MByte
Speicherverbrauch pro Collout 1.50KByte
Speicherverbrauch, wenn 100.000 Collouts gestartet und der Kontextwechsel 1 Million Mal ausgeführt wird 336.30MByte
Speicherverbrauch pro Person, wenn der Kontextwechsel 1 Million Mal ausgeführt wird 3.44KByte

Die Verarbeitung von Python async / await ist geeignet für

Verarbeitung zur asynchronen Ausführung mehrerer Netzwerk-E / A und Datei-E / A.

Versuchen Sie es mit Async / Warten

Schreiben Sie einen regulären FizzBuzz

Gewöhnlicher Fizz Buzz


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 mit einem Collout mit Async / Warten

Das Ergebnis ist das gleiche, da es nur in der Corroutine ausgeführt wird. スクリーンショット 2015-11-03 18.59.47.png

1 Kollout


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()
#Rufen Sie die Hauptfunktion im Collout auf
loop.run_until_complete(main())
loop.close()

Async / await führt 100.000 Collouts von FizzBuzz asynchron aus

Generieren Sie 100.000 Collouts und führen Sie sie gleichzeitig aus. Wenn eine Coroutine die Ausführung beendet hat, wechselt der Kontext und die nächste Coroutine wird ausgeführt. スクリーンショット 2015-11-03 18.52.02.png

Corroutine 100.000 gleichzeitige Ausführung


# -*- 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()
#Generieren Sie 100.000 Collouts
tasks = asyncio.wait([task_fizzbuzz(str(i) + ":") for i in range(1, 100000)])
loop.run_until_complete(tasks)
loop.close()

Ausführungsergebnis von 100.000 Collouts


....
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 läuft asynchron mit 100.000 Collouts FizzBuzz mit Schlaf

Dies ist ein Test, um festzustellen, ob der Kontext beim Schlafen während der Fizzbuzz-Logik erfolgreich wechselt.

100.000 gleichzeitige Hinrichtungen von Kollouts mit Schlaf


# -*- 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) #Neu hinzugefügter Code
        print(prefix + "{}:".format(str(x)) + fizzbuzz(x))
    return None

loop = asyncio.get_event_loop()
#Generieren Sie 100.000 Collouts
tasks = asyncio.wait([task_fizzbuzz(str(i) + ":") for i in range(1, 100000)])
#Parallele Ausführung
loop.run_until_complete(tasks)
loop.close()

Ausführungsergebnis von 100.000 Coroutinen mit Schlaf


....
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
....

Wenn Sie mit "wait asyncio.sleep (1)" schlafen, während die Coroutine ausgeführt wird, erhalten Sie das Ergebnis, dass sie gleichzeitig ausgeführt wird, da sie zu einer anderen Coroutine wechselt. スクリーンショット 2015-11-03 19.25.56.png

Nehmen Sie einen Benchmark

Nachdem die Überprüfung abgeschlossen ist, werden wir den Benchmark mit den folgenden drei Programmen durchführen.

  1. Ein Programm, das FizzBuzz 10 x 100.000 Mal ohne Verwendung von Collouts ausführt
  2. Ein Programm, das 100.000 Collouts startet und FizzBuzz 10 x 100.000 Mal ausführt
  3. Ein Programm, das FizzBuzz 10-mal x 100.000-mal ausführt, insgesamt 1 Million Kontextwechsel ausführt, indem 100.000 Coroutinen gestartet und Sleep für jedes FizzBuzz ausgeführt werden.

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

1. Kein 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

#Messung starten
ts = time.time()

#10 mal FizzBuzz x 100.000 mal
for x in range(COUNT):
    for x in range(FIZZBUZZ_COUNT):
        print(fizzbuzz(x))
#Warten Sie 10 Sekunden, bis der Zustand mit den anderen übereinstimmt
for x in range(FIZZBUZZ_COUNT):
    time.sleep(1)

#Ende der Messung
te = time.time()

#Ergebnisausgabe
print("{}sec".format(te-ts))


2. Starten Sie 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

#Messung starten
ts = time.time()

#10 mal FizzBuzz x 100.000 mal
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()

#Warten Sie 10 Sekunden, bis der Zustand mit den anderen übereinstimmt
for x in range(FIZZBUZZ_COUNT):
    time.sleep(1)

#Ende der Messung
te = time.time()

#Ergebnisausgabe
print("{}sec".format(te-ts))

3. Starten Sie 100.000 Collouts. Kontextwechsel 1 Million Mal

# -*- 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

#Messung starten
ts = time.time()

#10 mal FizzBuzz x 100.000 mal
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()

#Ende der Messung
te = time.time()

#Ergebnisausgabe
print("{}sec".format(te-ts))

Benchmark-Ergebnisse

Ich mache es jeweils nur dreimal. Der Kontextwechsel dauert zu lange (›´ω`‹) Ich habe es nicht geschrieben, um die Ergebnisse einfach zu halten, aber Benchmark 2 scheint 100.000 Kontextwechsel stattgefunden zu haben.

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

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

Referenz

PEP 0492 -- Coroutines with async and await syntax 18.5.3. Aufgaben und Collouts 18.5.9. Develop with asyncio Was ist neu in Python 3.5 How to use async/await in Python 3.5? Asynchrone Programmierung mit Async und Await (C # und Visual Basic) (https://msdn.microsoft.com/en-us/library/hh191443.aspx) AsyncIO vs Gevent? : Python - Reddit

Recommended Posts

Leichter Thread-Leistungsbenchmark mit async / await, implementiert in Python 3.5
Scraping mit Python 3.5 async / await
Verstecke Websockets asynchron / warte in Python3
SimRank in Python implementiert
Python async / warte auf Kuriosität
Shiritori in Python implementiert
Konvertieren Sie die asynchrone API im Callback-Stil in async / await in Python
Scraping mit Python 3.5 Async-Syntax
Führen Sie den in Python (Flask) implementierten LINE Bot "ohne Verwendung von Heroku" aus.
Implementierte Supreme Solver in Python 3
Übersetzt mit Googletrans in Python
Verwenden des Python-Modus in der Verarbeitung
GUI-Programmierung in Python mit Appjar
Vorsichtsmaßnahmen bei der Verwendung von Pit mit Python
Implementierte Bildsegmentierung in Python (Union-Find)
Versuchen Sie es mit LevelDB mit Python (plyvel)
In Python implementierte Widrow-Hoff-Lernregeln
Implementierte Methode zur Weitergabe von Etiketten in Python
[Python] Asynchrone Anfrage mit async / await
Verwendung globaler Variablen in Python-Funktionen
Mal sehen, wie man Eingaben in Python verwendet
Gesamtleistung in Python (mit Funktools)
Implementierte Perceptron-Lernregeln in Python
Handschriftliche Zeichenerkennung mit KNN in Python
Versuchen Sie es mit LeapMotion mit Python
Implementiert in 1 Minute! LINE Benachrichtigen in Python
Suche nach Tiefenpriorität mit Stack in Python
Bei Verwendung regulärer Ausdrücke in Python
GUI-Erstellung in Python mit tkinter 2
Mausbedienung mit Windows-API in Python
Hinweise zur Verwendung von cChardet und python3-chardet in Python 3.3.1.
Versuchen Sie es mit der Wunderlist-API in Python
GUI-Erstellung in Python mit tkinter Teil 1
Ein einfacher HTTP-Client, der in Python implementiert ist
Holen Sie sich Suica Balance in Python (mit libpafe)
Übung, dies in Python zu verwenden (schlecht)
Hash-Passwörter langsam mit bcrypt in Python
Versuchen Sie, die Kraken-API mit Python zu verwenden
Verwenden von venv in der Windows + Docker-Umgebung [Python]
Großer Unterschied in der Leistung von Ruby, Python und httpd
Implementiert in Python PRML Kapitel 7 Nichtlineare SVM
[FX] Hit oanda-API mit Python mit Docker
Tweet mit der Twitter-API in Python
[Python] [Windows] Serielle Kommunikation in Python über DLL
Ich habe versucht, die Bayes'sche Optimierung von Python zu verwenden
Melden Sie sich mit Anforderungen in Python bei Slack an
Holen Sie sich Youtube-Daten in Python mithilfe der Youtube-Daten-API
Ich habe versucht, Couseras logistische Regression in Python zu implementieren
Verwenden physikalischer Konstanten in Python scipy.constants ~ Konstante e ~
Scraping von Websites mit JavaScript in Python
Entwicklung eines Slack Bot mit Python mit chat.postMessage
Schreiben Sie mit f2py ein Python-Modul in fortran
Zeichnen Sie mit graphviz eine Baumstruktur in Python 3
Implementiert in Python PRML Kapitel 5 Neuronales Netzwerk
Hinweise zur Verwendung von Python (Pydev) mit Eclipse
Krankheitsklassifizierung durch Random Forest mit Python
Stuge Sort in Python 3 implementiert (Bubble Sort & Quick Sort)
Implementiert in Python PRML Kapitel 1 Bayesianische Schätzung
Laden Sie Dateien in jedem Format mit Python herunter