summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2010-11-04 16:51:32 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2010-11-04 16:51:32 (GMT)
commit2397dd58b70986db898f689fe7a1597cdd51f29f (patch)
treedfbb92e9a134cc2bd9c9621a89a6bd9c17802128
parent5ee89cf13ee8d1bfd2f56bca0432e23ba1009f1f (diff)
downloadcpython-2397dd58b70986db898f689fe7a1597cdd51f29f.zip
cpython-2397dd58b70986db898f689fe7a1597cdd51f29f.tar.gz
cpython-2397dd58b70986db898f689fe7a1597cdd51f29f.tar.bz2
Issue #10314: improve performance of JSON encoding with sort_keys=True
-rw-r--r--Modules/_json.c45
1 files changed, 25 insertions, 20 deletions
diff --git a/Modules/_json.c b/Modules/_json.c
index dd9749b..75b14ee 100644
--- a/Modules/_json.c
+++ b/Modules/_json.c
@@ -1387,8 +1387,6 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
PyObject *item = NULL;
int skipkeys;
Py_ssize_t idx;
- PyObject *mapping;
- static PyObject *code = NULL;
if (open_dict == NULL || close_dict == NULL || empty_dict == NULL) {
open_dict = PyUnicode_InternFromString("{");
@@ -1430,30 +1428,37 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
}
if (PyObject_IsTrue(s->sort_keys)) {
- if (code == NULL) {
- code = Py_CompileString("sorted(d.items(), key=lambda kv: kv[0])",
- "_json.c", Py_eval_input);
- if (code == NULL)
- goto bail;
- }
-
- mapping = PyDict_New();
- if (mapping == NULL)
+ /* First sort the keys then replace them with (key, value) tuples. */
+ Py_ssize_t i, nitems;
+ items = PyMapping_Keys(dct);
+ if (items == NULL)
goto bail;
- if (PyDict_SetItemString(mapping, "d", dct) == -1) {
- Py_DECREF(mapping);
+ if (!PyList_Check(items)) {
+ PyErr_SetString(PyExc_ValueError, "keys must return list");
goto bail;
}
- items = PyEval_EvalCode((PyCodeObject *)code, PyEval_GetGlobals(), mapping);
- Py_DECREF(mapping);
- } else {
- items = PyMapping_Items(dct);
+ if (PyList_Sort(items) < 0)
+ goto bail;
+ nitems = PyList_GET_SIZE(items);
+ for (i = 0; i < nitems; i++) {
+ PyObject *key, *value;
+ key = PyList_GET_ITEM(items, i);
+ value = PyDict_GetItem(dct, key);
+ item = PyTuple_Pack(2, key, value);
+ if (item == NULL)
+ goto bail;
+ PyList_SET_ITEM(items, i, item);
+ Py_DECREF(key);
}
- if (items == NULL)
+ }
+ else {
+ items = PyMapping_Items(dct);
+ }
+ if (items == NULL)
goto bail;
it = PyObject_GetIter(items);
- Py_DECREF(items);
- if (it == NULL)
+ Py_DECREF(items);
+ if (it == NULL)
goto bail;
skipkeys = PyObject_IsTrue(s->skipkeys);
idx = 0;