In letzter Zeit verwende ich Python, um Webprogramme zu entwickeln, und verwende dann immer mehrere Threads für die Anforderungsverarbeitung. Ein Problem besteht darin, dass die Antwortzeit jeder Anforderung sichergestellt werden muss sehr kurz, sonst solange Wenn die Anfrage zu langsam ist, verweigert der Server den Dienst, da kein Thread auf die Anfrage antworten kann. Normalerweise wird unser Dienst auf Leistung getestet, wenn er online geht, sodass es im Normalfall keine großen Probleme gibt Es ist jedoch unmöglich, alle Szenarien zu testen. Wenn es erscheint, werden einige Teile nicht verfügbar sein. Später habe ich auf Coroutine und Greenlet umgestellt Ich habe ein einfaches Verständnis des Implementierungsmechanismus.
Jedes Greenlet ist nur ein Heap. Ein Python-Objekt (PyGreenlet) in . Es ist also kein Problem, Millionen oder sogar Dutzende Millionen Greenlets für einen Prozess zu erstellen >
typedef struct _greenlet { PyObject_HEAD char* stack_start; char* stack_stop; char* stack_copy; intptr_t stack_saved; struct _greenlet* stack_prev; struct _greenlet* parent; PyObject* run_info; struct _frame* top_frame; int recursion_depth; PyObject* weakreflist; PyObject* exc_type; PyObject* exc_value; PyObject* exc_traceback; PyObject* dict; } PyGreenlet;
Das Folgende ist ein einfaches Stapelraummodell von Greenlet (von greenlet.c)
A PyGreenlet is a range of C stack addresses that must be saved and restored in such a way that the full range of the stack contains valid data when we switch to it. Stack layout for a greenlet: | ^^^ | | older data | | | stack_stop . |_______________| . | | . | greenlet data | . | in stack | . * |_______________| . . _____________ stack_copy + stack_saved . | | | | . | data | |greenlet data| . | unrelated | | saved | . | to | | in heap | stack_start . | this | . . |_____________| stack_copy | greenlet | | | | newer data | | vvv |
from greenlet import greenlet def test1(): print 12 gr2.switch() print 34 def test2(): print 56 gr1.switch() print 78 gr1 = greenlet(test1) gr2 = greenlet(test2) gr1.switch()