Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 25 additions & 29 deletions gmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,24 @@
#include <stdlib.h>
#include <string.h>

#if !defined(PYPY_VERSION)
# define MAX_CACHE_SIZE 100
#else
# define MAX_CACHE_SIZE 0
#define ON_CPYTHON 1
#if defined(PYPY_VERSION) || defined(GRAALVM_PYTHON)
# undef ON_CPYTHON
#endif
#define MAX_CACHED_SIZEOF 256

#ifdef ON_CPYTHON
# define MAX_FREELIST_SIZE 100
# define MAX_FREELIST_SIZEOF 256

typedef struct {
MPZ_Object *gmp_cache[MAX_CACHE_SIZE + 1];
size_t gmp_cache_size;
MPZ_Object *freelist[MAX_FREELIST_SIZE + 1];
size_t freelist_size;
} gmp_global;

_Thread_local gmp_global global = {
.gmp_cache_size = 0,
.freelist_size = 0,
};
#endif

uint8_t bits_per_digit;
Py_hash_t pyhash_modulus;
Expand All @@ -31,20 +34,24 @@ MPZ_new(void)
{
MPZ_Object *res;

if (global.gmp_cache_size) {
res = global.gmp_cache[--global.gmp_cache_size];
#ifdef ON_CPYTHON
if (global.freelist_size) {
res = global.freelist[--global.freelist_size];
(void)zz_set(0, &res->z);
Py_XINCREF((PyObject *)res);
Py_INCREF((PyObject *)res);
}
else {
#endif
res = PyObject_New(MPZ_Object, &MPZ_Type);
if (!res) {
return NULL; /* LCOV_EXCL_LINE */
}
if (zz_init(&res->z)) {
return (MPZ_Object *)PyErr_NoMemory(); /* LCOV_EXCL_LINE */
}
#ifdef ON_CPYTHON
}
#endif
res->hash_cache = -1;
return res;
}
Expand Down Expand Up @@ -644,13 +651,15 @@ dealloc(PyObject *self)
{
MPZ_Object *u = (MPZ_Object *)self;

if (global.gmp_cache_size < MAX_CACHE_SIZE
&& zz_sizeof(&u->z) <= MAX_CACHED_SIZEOF
#ifdef ON_CPYTHON
if (global.freelist_size < MAX_FREELIST_SIZE
&& zz_sizeof(&u->z) <= MAX_FREELIST_SIZEOF
&& MPZ_CheckExact(self))
{
global.gmp_cache[global.gmp_cache_size++] = u;
global.freelist[global.freelist_size++] = u;
}
else {
#endif
freefunc tp_free;

if (MPZ_CheckExact(self)) {
Expand All @@ -661,7 +670,9 @@ dealloc(PyObject *self)
}
zz_clear(&u->z);
tp_free(self);
#ifdef ON_CPYTHON
}
#endif
}

static PyObject *
Expand Down Expand Up @@ -2611,19 +2622,6 @@ gmp__mpmath_create(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
return Py_BuildValue("(bNNK)", negative, man, iexp, bc);
}

static PyObject *
gmp__free_cache(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
while (global.gmp_cache_size) {
MPZ_Object *u = global.gmp_cache[--global.gmp_cache_size];
PyObject *self = (PyObject *)u;

zz_clear(&u->z);
PyObject_Free(self);
}
Py_RETURN_NONE;
}

static PyMethodDef gmp_functions[] = {
{"gcd", (PyCFunction)gmp_gcd, METH_FASTCALL,
("gcd($module, /, *integers)\n--\n\n"
Expand Down Expand Up @@ -2656,8 +2654,6 @@ static PyMethodDef gmp_functions[] = {
{"_mpmath_create", (PyCFunction)gmp__mpmath_create, METH_FASTCALL,
("_mpmath_create($module, man, exp, prec=0, rnd='d', /)\n--\n\n"
"Helper function for mpmath.")},
{"_free_cache", gmp__free_cache, METH_NOARGS,
"_free_cache($module)\n--\n\nFree mpz's cache."},
{NULL} /* sentinel */
};

Expand Down
8 changes: 0 additions & 8 deletions tests/test_mpz.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import sys
import warnings
from concurrent.futures import ThreadPoolExecutor
from subprocess import run

import pytest
from gmp import mpz
Expand Down Expand Up @@ -1093,10 +1092,3 @@ def test_int_api():
continue
mz_sig = inspect.signature(mz)
assert m_sig == mz_sig


def test_mpz_clear():
# for coverage (test module cleanup)
res = run([sys.executable, "-c",
"import gmp; a = gmp.mpz(1); del a; gmp._free_cache()"])
assert res.returncode == 0