Skip to content

Commit

Permalink
More efficient module state access in top-level functions
Browse files Browse the repository at this point in the history
Top-level functions defined using the c-api have the module object
passed as `self`, there's no need to go through `PyState_FindModule` for
these functions.

This shaves ~5 ns off the call time per function, which is ~6% of the
overhead of a `msgspec.json.encode` call.
  • Loading branch information
jcrist committed Aug 16, 2023
1 parent ab18d40 commit 5a5e507
Showing 1 changed file with 10 additions and 9 deletions.
19 changes: 10 additions & 9 deletions msgspec/_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -6121,7 +6121,7 @@ msgspec_defstruct(PyObject *self, PyObject *args, PyObject *kwargs)
)
return NULL;

MsgspecState *mod = msgspec_get_global_state();
MsgspecState *mod = msgspec_get_state(self);

/* Handle namespace */
if (namespace == NULL || namespace == Py_None) {
Expand Down Expand Up @@ -8782,14 +8782,15 @@ encoder_encode_common(

static PyObject*
encode_common(
PyObject *module,
PyObject *const *args,
Py_ssize_t nargs,
PyObject *kwnames,
int(*encode)(EncoderState*, PyObject*)
)
{
PyObject *enc_hook = NULL;
MsgspecState *mod = msgspec_get_global_state();
MsgspecState *mod = msgspec_get_state(module);

/* Parse arguments */
if (!check_positional_nargs(nargs, 1, 1)) return NULL;
Expand Down Expand Up @@ -12488,7 +12489,7 @@ PyDoc_STRVAR(msgspec_msgpack_encode__doc__,
static PyObject*
msgspec_msgpack_encode(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
return encode_common(args, nargs, kwnames, &mpack_encode);
return encode_common(self, args, nargs, kwnames, &mpack_encode);
}

/*************************************************************************
Expand Down Expand Up @@ -13524,7 +13525,7 @@ PyDoc_STRVAR(msgspec_json_encode__doc__,
static PyObject*
msgspec_json_encode(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
return encode_common(args, nargs, kwnames, &json_encode);
return encode_common(self, args, nargs, kwnames, &json_encode);
}

/*************************************************************************
Expand Down Expand Up @@ -15318,7 +15319,7 @@ msgspec_msgpack_decode(PyObject *self, PyObject *const *args, Py_ssize_t nargs,
{
PyObject *res = NULL, *buf = NULL, *type = NULL, *strict_obj = NULL;
PyObject *dec_hook = NULL, *ext_hook = NULL;
MsgspecState *mod = msgspec_get_global_state();
MsgspecState *mod = msgspec_get_state(self);
int strict = 1;

/* Parse arguments */
Expand Down Expand Up @@ -18072,7 +18073,7 @@ msgspec_json_format(PyObject *self, PyObject *args, PyObject *kwargs)
dec.input_end = dec.input_pos + buffer.len;

/* Init encoder */
enc.mod = msgspec_get_global_state();
enc.mod = msgspec_get_state(self);
enc.enc_hook = NULL;
/* Assume pretty-printing will take at least as much space as the
* input. This is true unless there's existing whitespace. */
Expand Down Expand Up @@ -18346,7 +18347,7 @@ msgspec_json_decode(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyO
{
PyObject *res = NULL, *buf = NULL, *type = NULL, *dec_hook = NULL, *strict_obj = NULL;
int strict = 1;
MsgspecState *mod = msgspec_get_global_state();
MsgspecState *mod = msgspec_get_state(self);

/* Parse arguments */
if (!check_positional_nargs(nargs, 1, 1)) return NULL;
Expand Down Expand Up @@ -19126,7 +19127,7 @@ msgspec_to_builtins(PyObject *self, PyObject *args, PyObject *kwargs)
return NULL;
}

state.mod = msgspec_get_global_state();
state.mod = msgspec_get_state(self);
state.str_keys = str_keys;
state.builtin_types = 0;
state.builtin_types_seq = NULL;
Expand Down Expand Up @@ -20662,7 +20663,7 @@ msgspec_convert(PyObject *self, PyObject *args, PyObject *kwargs)
return NULL;
}

state.mod = msgspec_get_global_state();
state.mod = msgspec_get_state(self);
state.builtin_types = 0;
state.from_attributes = from_attributes;
state.strict = strict;
Expand Down

0 comments on commit 5a5e507

Please sign in to comment.