summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorInada Naoki <songofacandy@gmail.com>2019-08-08 17:57:10 +0900
committerGitHub <noreply@github.com>2019-08-08 17:57:10 +0900
commit2a570af12ac5e4ac5575a68f8739b31c24d01367 (patch)
tree0f1714b6c8defe05ac81bc17863d6eb479117e04
parente43e7ed36480190083740fd75e2b9cdca72f1a68 (diff)
downloadcpython-git-2a570af12ac5e4ac5575a68f8739b31c24d01367.tar.gz
bpo-37587: optimize json.loads (GH-15134)
Use a tighter scope temporary variable to help register allocation. 1% speedup for large string. Use PyDict_SetItemDefault() for memoizing keys. At most 4% speedup when the cache hit ratio is low.
-rw-r--r--Modules/_json.c39
1 files changed, 19 insertions, 20 deletions
diff --git a/Modules/_json.c b/Modules/_json.c
index 76da1d345e..112903ea57 100644
--- a/Modules/_json.c
+++ b/Modules/_json.c
@@ -433,16 +433,21 @@ scanstring_unicode(PyObject *pystr, Py_ssize_t end, int strict, Py_ssize_t *next
}
while (1) {
/* Find the end of the string or the next escape */
- Py_UCS4 c = 0;
- for (next = end; next < len; next++) {
- c = PyUnicode_READ(kind, buf, next);
- if (c == '"' || c == '\\') {
- break;
- }
- else if (c <= 0x1f && strict) {
- raise_errmsg("Invalid control character at", pystr, next);
- goto bail;
+ Py_UCS4 c;
+ {
+ // Use tight scope variable to help register allocation.
+ Py_UCS4 d = 0;
+ for (next = end; next < len; next++) {
+ d = PyUnicode_READ(kind, buf, next);
+ if (d == '"' || d == '\\') {
+ break;
+ }
+ if (d <= 0x1f && strict) {
+ raise_errmsg("Invalid control character at", pystr, next);
+ goto bail;
+ }
}
+ c = d;
}
if (!(c == '"' || c == '\\')) {
raise_errmsg("Unterminated string starting at", pystr, begin);
@@ -749,19 +754,13 @@ _parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ss
key = scanstring_unicode(pystr, idx + 1, s->strict, &next_idx);
if (key == NULL)
goto bail;
- memokey = PyDict_GetItemWithError(s->memo, key);
- if (memokey != NULL) {
- Py_INCREF(memokey);
- Py_DECREF(key);
- key = memokey;
- }
- else if (PyErr_Occurred()) {
+ memokey = PyDict_SetDefault(s->memo, key, key);
+ if (memokey == NULL) {
goto bail;
}
- else {
- if (PyDict_SetItem(s->memo, key, key) < 0)
- goto bail;
- }
+ Py_INCREF(memokey);
+ Py_DECREF(key);
+ key = memokey;
idx = next_idx;
/* skip whitespace between key and : delimiter, read :, skip whitespace */