GitHub

@@ -1162,7 +1162,7 @@ typedef enum {

11621162

} AwaitableState;

11631163116411641165-

typedef struct {

1165+

typedef struct PyAsyncGenASend {

11661166

PyObject_HEAD

11671167

PyAsyncGenObject *ags_gen;

11681168

@@ -1174,7 +1174,7 @@ typedef struct {

11741174

} PyAsyncGenASend;

11751175117611761177-

typedef struct {

1177+

typedef struct PyAsyncGenAThrow {

11781178

PyObject_HEAD

11791179

PyAsyncGenObject *agt_gen;

11801180

@@ -1186,28 +1186,12 @@ typedef struct {

11861186

} PyAsyncGenAThrow;

11871187118811881189-

typedef struct {

1189+

typedef struct _PyAsyncGenWrappedValue {

11901190

PyObject_HEAD

11911191

PyObject *agw_val;

11921192

} _PyAsyncGenWrappedValue;

11931193119411941195-

#ifndef _PyAsyncGen_MAXFREELIST

1196-

#define _PyAsyncGen_MAXFREELIST 80

1197-

#endif

1198-1199-

/* Freelists boost performance 6-10%; they also reduce memory

1200-

fragmentation, as _PyAsyncGenWrappedValue and PyAsyncGenASend

1201-

are short-living objects that are instantiated for every

1202-

__anext__ call.

1203-

*/

1204-1205-

static _PyAsyncGenWrappedValue *ag_value_freelist[_PyAsyncGen_MAXFREELIST];

1206-

static int ag_value_freelist_free = 0;

1207-1208-

static PyAsyncGenASend *ag_asend_freelist[_PyAsyncGen_MAXFREELIST];

1209-

static int ag_asend_freelist_free = 0;

1210-12111195

#define _PyAsyncGenWrappedValue_CheckExact(o) \

12121196

Py_IS_TYPE(o, &_PyAsyncGenWrappedValue_Type)

12131197

@@ -1423,27 +1407,29 @@ PyAsyncGen_New(PyFrameObject *f, PyObject *name, PyObject *qualname)

142314071424140814251409

void

1426-

_PyAsyncGen_ClearFreeLists(void)

1410+

_PyAsyncGen_ClearFreeLists(PyThreadState *tstate)

14271411

{

1428-

while (ag_value_freelist_free) {

1412+

struct _Py_async_gen_state *state = &tstate->interp->async_gen;

1413+1414+

while (state->value_numfree) {

14291415

_PyAsyncGenWrappedValue *o;

1430-

o = ag_value_freelist[--ag_value_freelist_free];

1416+

o = state->value_freelist[--state->value_numfree];

14311417

assert(_PyAsyncGenWrappedValue_CheckExact(o));

14321418

PyObject_GC_Del(o);

14331419

}

143414201435-

while (ag_asend_freelist_free) {

1421+

while (state->asend_numfree) {

14361422

PyAsyncGenASend *o;

1437-

o = ag_asend_freelist[--ag_asend_freelist_free];

1423+

o = state->asend_freelist[--state->asend_numfree];

14381424

assert(Py_IS_TYPE(o, &_PyAsyncGenASend_Type));

14391425

PyObject_GC_Del(o);

14401426

}

14411427

}

1442142814431429

void

1444-

_PyAsyncGen_Fini(void)

1430+

_PyAsyncGen_Fini(PyThreadState *tstate)

14451431

{

1446-

_PyAsyncGen_ClearFreeLists();

1432+

_PyAsyncGen_ClearFreeLists(tstate);

14471433

}

1448143414491435

@@ -1486,10 +1472,13 @@ async_gen_asend_dealloc(PyAsyncGenASend *o)

14861472

_PyObject_GC_UNTRACK((PyObject *)o);

14871473

Py_CLEAR(o->ags_gen);

14881474

Py_CLEAR(o->ags_sendval);

1489-

if (ag_asend_freelist_free < _PyAsyncGen_MAXFREELIST) {

1475+

PyInterpreterState *interp = _PyInterpreterState_GET();

1476+

struct _Py_async_gen_state *state = &interp->async_gen;

1477+

if (state->asend_numfree < _PyAsyncGen_MAXFREELIST) {

14901478

assert(PyAsyncGenASend_CheckExact(o));

1491-

ag_asend_freelist[ag_asend_freelist_free++] = o;

1492-

} else {

1479+

state->asend_freelist[state->asend_numfree++] = o;

1480+

}

1481+

else {

14931482

PyObject_GC_Del(o);

14941483

}

14951484

}

@@ -1641,11 +1630,14 @@ static PyObject *

16411630

async_gen_asend_new(PyAsyncGenObject *gen, PyObject *sendval)

16421631

{

16431632

PyAsyncGenASend *o;

1644-

if (ag_asend_freelist_free) {

1645-

ag_asend_freelist_free--;

1646-

o = ag_asend_freelist[ag_asend_freelist_free];

1633+

PyInterpreterState *interp = _PyInterpreterState_GET();

1634+

struct _Py_async_gen_state *state = &interp->async_gen;

1635+

if (state->asend_numfree) {

1636+

state->asend_numfree--;

1637+

o = state->asend_freelist[state->asend_numfree];

16471638

_Py_NewReference((PyObject *)o);

1648-

} else {

1639+

}

1640+

else {

16491641

o = PyObject_GC_New(PyAsyncGenASend, &_PyAsyncGenASend_Type);

16501642

if (o == NULL) {

16511643

return NULL;

@@ -1673,10 +1665,13 @@ async_gen_wrapped_val_dealloc(_PyAsyncGenWrappedValue *o)

16731665

{

16741666

_PyObject_GC_UNTRACK((PyObject *)o);

16751667

Py_CLEAR(o->agw_val);

1676-

if (ag_value_freelist_free < _PyAsyncGen_MAXFREELIST) {

1668+

PyInterpreterState *interp = _PyInterpreterState_GET();

1669+

struct _Py_async_gen_state *state = &interp->async_gen;

1670+

if (state->value_numfree < _PyAsyncGen_MAXFREELIST) {

16771671

assert(_PyAsyncGenWrappedValue_CheckExact(o));

1678-

ag_value_freelist[ag_value_freelist_free++] = o;

1679-

} else {

1672+

state->value_freelist[state->value_numfree++] = o;

1673+

}

1674+

else {

16801675

PyObject_GC_Del(o);

16811676

}

16821677

}

@@ -1740,12 +1735,15 @@ _PyAsyncGenValueWrapperNew(PyObject *val)

17401735

_PyAsyncGenWrappedValue *o;

17411736

assert(val);

174217371743-

if (ag_value_freelist_free) {

1744-

ag_value_freelist_free--;

1745-

o = ag_value_freelist[ag_value_freelist_free];

1738+

PyInterpreterState *interp = _PyInterpreterState_GET();

1739+

struct _Py_async_gen_state *state = &interp->async_gen;

1740+

if (state->value_numfree) {

1741+

state->value_numfree--;

1742+

o = state->value_freelist[state->value_numfree];

17461743

assert(_PyAsyncGenWrappedValue_CheckExact(o));

17471744

_Py_NewReference((PyObject*)o);

1748-

} else {

1745+

}

1746+

else {

17491747

o = PyObject_GC_New(_PyAsyncGenWrappedValue,

17501748

&_PyAsyncGenWrappedValue_Type);

17511749

if (o == NULL) {

Read the original on github.com ↗