Skip to content

Commit ac8bf39

Browse files
committed
(un)pickling now is only a little slower than dict!
1 parent 539fb87 commit ac8bf39

5 files changed

Lines changed: 159 additions & 49 deletions

File tree

src/frozendict/c_src/3_10/frozendictobject.c

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -887,21 +887,43 @@ static Py_ssize_t dict_get_index(PyDictObject *self, PyObject *key) {
887887
return (self->ma_keys->dk_lookup) (self, key, hash, &val);
888888
}
889889

890-
static PyObject *
891-
frozendict_reduce(PyFrozenDictObject* mp, PyObject *Py_UNUSED(ignored))
892-
{
893-
PyObject *d = PyDict_New();
894-
895-
if (d == NULL) {
890+
static PyObject * frozendict_reduce(
891+
PyFrozenDictObject *self,
892+
PyObject *Py_UNUSED(ignored)
893+
) {
894+
const PyObject *o = PyDict_Type.tp_alloc(&PyDict_Type, 0);
895+
896+
if (o == NULL) {
896897
return NULL;
897898
}
898899

899-
if (PyDict_Merge(d, (PyObject *)mp, 1)) {
900+
PyDictObject *d = (PyDictObject *)o;
901+
PyDictKeysObject *keys = clone_combined_dict_keys(
902+
(PyDictObject*) self
903+
);
904+
905+
if (keys == NULL) {
900906
Py_DECREF(d);
901907
return NULL;
902908
}
903-
904-
return Py_BuildValue("O(N)", Py_TYPE(mp), d);
909+
910+
d->ma_keys = keys;
911+
d->ma_values = NULL;
912+
d->ma_used = self->ma_used;
913+
d->ma_version_tag = DICT_NEXT_VERSION();
914+
ASSERT_CONSISTENT(d);
915+
916+
const PyObject *args = PyTuple_Pack(1, d);
917+
Py_DECREF(d);
918+
919+
if (args == NULL) {
920+
return NULL;
921+
}
922+
923+
const PyObject *tuple = PyTuple_Pack(2, Py_TYPE(self), args);
924+
Py_DECREF(args);
925+
926+
return tuple;
905927
}
906928

907929
static PyObject* frozendict_clone(PyObject* self) {

src/frozendict/c_src/3_6/frozendictobject.c

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -899,21 +899,43 @@ static Py_ssize_t dict_get_index(PyDictObject *self, PyObject *key) {
899899
return (self->ma_keys->dk_lookup) (self, key, hash, &val, NULL);
900900
}
901901

902-
static PyObject *
903-
frozendict_reduce(PyFrozenDictObject* mp, PyObject *Py_UNUSED(ignored))
904-
{
905-
PyObject *d = PyDict_New();
906-
907-
if (d == NULL) {
902+
static PyObject * frozendict_reduce(
903+
PyFrozenDictObject *self,
904+
PyObject *Py_UNUSED(ignored)
905+
) {
906+
const PyObject *o = PyDict_Type.tp_alloc(&PyDict_Type, 0);
907+
908+
if (o == NULL) {
908909
return NULL;
909910
}
910-
911-
if (PyDict_Merge(d, (PyObject *)mp, 1)) {
911+
912+
PyDictObject *d = (PyDictObject *)o;
913+
PyDictKeysObject *keys = clone_combined_dict_keys(
914+
(PyDictObject*) self
915+
);
916+
917+
if (keys == NULL) {
912918
Py_DECREF(d);
913919
return NULL;
914920
}
915-
916-
return Py_BuildValue("O(N)", Py_TYPE(mp), d);
921+
922+
d->ma_keys = keys;
923+
d->ma_values = NULL;
924+
d->ma_used = self->ma_used;
925+
d->ma_version_tag = DICT_NEXT_VERSION();
926+
ASSERT_CONSISTENT(d);
927+
928+
const PyObject *args = PyTuple_Pack(1, d);
929+
Py_DECREF(d);
930+
931+
if (args == NULL) {
932+
return NULL;
933+
}
934+
935+
const PyObject *tuple = PyTuple_Pack(2, Py_TYPE(self), args);
936+
Py_DECREF(args);
937+
938+
return tuple;
917939
}
918940

919941
static PyObject* frozendict_clone(PyObject* self) {

src/frozendict/c_src/3_7/frozendictobject.c

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -893,21 +893,43 @@ static Py_ssize_t dict_get_index(PyDictObject *self, PyObject *key) {
893893
return (self->ma_keys->dk_lookup) (self, key, hash, &val);
894894
}
895895

896-
static PyObject *
897-
frozendict_reduce(PyFrozenDictObject* mp, PyObject *Py_UNUSED(ignored))
898-
{
899-
PyObject *d = PyDict_New();
900-
901-
if (d == NULL) {
896+
static PyObject * frozendict_reduce(
897+
PyFrozenDictObject *self,
898+
PyObject *Py_UNUSED(ignored)
899+
) {
900+
const PyObject *o = PyDict_Type.tp_alloc(&PyDict_Type, 0);
901+
902+
if (o == NULL) {
902903
return NULL;
903904
}
904-
905-
if (PyDict_Merge(d, (PyObject *)mp, 1)) {
905+
906+
PyDictObject *d = (PyDictObject *)o;
907+
PyDictKeysObject *keys = clone_combined_dict_keys(
908+
(PyDictObject*) self
909+
);
910+
911+
if (keys == NULL) {
906912
Py_DECREF(d);
907913
return NULL;
908914
}
909-
910-
return Py_BuildValue("O(N)", Py_TYPE(mp), d);
915+
916+
d->ma_keys = keys;
917+
d->ma_values = NULL;
918+
d->ma_used = self->ma_used;
919+
d->ma_version_tag = DICT_NEXT_VERSION();
920+
ASSERT_CONSISTENT(d);
921+
922+
const PyObject *args = PyTuple_Pack(1, d);
923+
Py_DECREF(d);
924+
925+
if (args == NULL) {
926+
return NULL;
927+
}
928+
929+
const PyObject *tuple = PyTuple_Pack(2, Py_TYPE(self), args);
930+
Py_DECREF(args);
931+
932+
return tuple;
911933
}
912934

913935
static PyObject* frozendict_clone(PyObject* self) {

src/frozendict/c_src/3_8/frozendictobject.c

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -893,21 +893,43 @@ static Py_ssize_t dict_get_index(PyDictObject *self, PyObject *key) {
893893
return (self->ma_keys->dk_lookup) (self, key, hash, &val);
894894
}
895895

896-
static PyObject *
897-
frozendict_reduce(PyFrozenDictObject* mp, PyObject *Py_UNUSED(ignored))
898-
{
899-
PyObject *d = PyDict_New();
900-
901-
if (d == NULL) {
896+
static PyObject * frozendict_reduce(
897+
PyFrozenDictObject *self,
898+
PyObject *Py_UNUSED(ignored)
899+
) {
900+
const PyObject *o = PyDict_Type.tp_alloc(&PyDict_Type, 0);
901+
902+
if (o == NULL) {
902903
return NULL;
903904
}
904-
905-
if (PyDict_Merge(d, (PyObject *)mp, 1)) {
905+
906+
PyDictObject *d = (PyDictObject *)o;
907+
PyDictKeysObject *keys = clone_combined_dict_keys(
908+
(PyDictObject*) self
909+
);
910+
911+
if (keys == NULL) {
906912
Py_DECREF(d);
907913
return NULL;
908914
}
909-
910-
return Py_BuildValue("O(N)", Py_TYPE(mp), d);
915+
916+
d->ma_keys = keys;
917+
d->ma_values = NULL;
918+
d->ma_used = self->ma_used;
919+
d->ma_version_tag = DICT_NEXT_VERSION();
920+
ASSERT_CONSISTENT(d);
921+
922+
const PyObject *args = PyTuple_Pack(1, d);
923+
Py_DECREF(d);
924+
925+
if (args == NULL) {
926+
return NULL;
927+
}
928+
929+
const PyObject *tuple = PyTuple_Pack(2, Py_TYPE(self), args);
930+
Py_DECREF(args);
931+
932+
return tuple;
911933
}
912934

913935
static PyObject* frozendict_clone(PyObject* self) {

src/frozendict/c_src/3_9/frozendictobject.c

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -893,21 +893,43 @@ static Py_ssize_t dict_get_index(PyDictObject *self, PyObject *key) {
893893
return (self->ma_keys->dk_lookup) (self, key, hash, &val);
894894
}
895895

896-
static PyObject *
897-
frozendict_reduce(PyFrozenDictObject* mp, PyObject *Py_UNUSED(ignored))
898-
{
899-
PyObject *d = PyDict_New();
900-
901-
if (d == NULL) {
896+
static PyObject * frozendict_reduce(
897+
PyFrozenDictObject *self,
898+
PyObject *Py_UNUSED(ignored)
899+
) {
900+
const PyObject *o = PyDict_Type.tp_alloc(&PyDict_Type, 0);
901+
902+
if (o == NULL) {
902903
return NULL;
903904
}
904-
905-
if (PyDict_Merge(d, (PyObject *)mp, 1)) {
905+
906+
PyDictObject *d = (PyDictObject *)o;
907+
PyDictKeysObject *keys = clone_combined_dict_keys(
908+
(PyDictObject*) self
909+
);
910+
911+
if (keys == NULL) {
906912
Py_DECREF(d);
907913
return NULL;
908914
}
909-
910-
return Py_BuildValue("O(N)", Py_TYPE(mp), d);
915+
916+
d->ma_keys = keys;
917+
d->ma_values = NULL;
918+
d->ma_used = self->ma_used;
919+
d->ma_version_tag = DICT_NEXT_VERSION();
920+
ASSERT_CONSISTENT(d);
921+
922+
const PyObject *args = PyTuple_Pack(1, d);
923+
Py_DECREF(d);
924+
925+
if (args == NULL) {
926+
return NULL;
927+
}
928+
929+
const PyObject *tuple = PyTuple_Pack(2, Py_TYPE(self), args);
930+
Py_DECREF(args);
931+
932+
return tuple;
911933
}
912934

913935
static PyObject* frozendict_clone(PyObject* self) {

0 commit comments

Comments
 (0)