aboutsummaryrefslogtreecommitdiff
path: root/ext/misc/json1.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2015-09-24 01:06:37 +0000
committerdrh <drh@noemail.net>2015-09-24 01:06:37 +0000
commit9567794fd931511bff5bcff1fe4c2749a28b65a4 (patch)
tree03f1e071349fc8f097f867ad8ce8cad728a2f31f /ext/misc/json1.c
parent58cb6dbe0d9d32386a61fba1812dfbacc594aa46 (diff)
downloadsqlite-9567794fd931511bff5bcff1fe4c2749a28b65a4.tar.gz
sqlite-9567794fd931511bff5bcff1fe4c2749a28b65a4.zip
Performance optimizations on the JSON parser.
FossilOrigin-Name: 7dd4b07a42eb84589d34430b9d7bfa88fbd743eb
Diffstat (limited to 'ext/misc/json1.c')
-rw-r--r--ext/misc/json1.c78
1 files changed, 65 insertions, 13 deletions
diff --git a/ext/misc/json1.c b/ext/misc/json1.c
index 3dd831f9c..cf766120c 100644
--- a/ext/misc/json1.c
+++ b/ext/misc/json1.c
@@ -37,10 +37,34 @@ SQLITE_EXTENSION_INIT1
** Versions of isspace(), isalnum() and isdigit() to which it is safe
** to pass signed char values.
*/
-#define safe_isspace(x) isspace((unsigned char)(x))
#define safe_isdigit(x) isdigit((unsigned char)(x))
#define safe_isalnum(x) isalnum((unsigned char)(x))
+/*
+** Growing our own isspace() routine this way is twice as fast as
+** the library isspace() function, resulting in a 7% overall performance
+** increase for the parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os).
+*/
+static const char jsonIsSpace[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+#define safe_isspace(x) (jsonIsSpace[(unsigned char)x])
+
/* Unsigned integer types */
typedef sqlite3_uint64 u64;
typedef unsigned int u32;
@@ -548,6 +572,44 @@ static void jsonReturn(
}
}
+/* Forward reference */
+static int jsonParseAddNode(JsonParse*,u32,u32,const char*);
+
+/*
+** A macro to hint to the compiler that a function should not be
+** inlined.
+*/
+#if defined(__GNUC__)
+# define JSON_NOINLINE __attribute__((noinline))
+#elif defined(_MSC_VER) && _MSC_VER>=1310
+# define JSON_NOINLINE __declspec(noinline)
+#else
+# define JSON_NOINLINE
+#endif
+
+
+static JSON_NOINLINE int jsonParseAddNodeExpand(
+ JsonParse *pParse, /* Append the node to this object */
+ u32 eType, /* Node type */
+ u32 n, /* Content size or sub-node count */
+ const char *zContent /* Content */
+){
+ u32 nNew;
+ JsonNode *pNew;
+ assert( pParse->nNode>=pParse->nAlloc );
+ if( pParse->oom ) return -1;
+ nNew = pParse->nAlloc*2 + 10;
+ pNew = sqlite3_realloc(pParse->aNode, sizeof(JsonNode)*nNew);
+ if( pNew==0 ){
+ pParse->oom = 1;
+ return -1;
+ }
+ pParse->nAlloc = nNew;
+ pParse->aNode = pNew;
+ assert( pParse->nNode<pParse->nAlloc );
+ return jsonParseAddNode(pParse, eType, n, zContent);
+}
+
/*
** Create a new JsonNode instance based on the arguments and append that
** instance to the JsonParse. Return the index in pParse->aNode[] of the
@@ -561,17 +623,7 @@ static int jsonParseAddNode(
){
JsonNode *p;
if( pParse->nNode>=pParse->nAlloc ){
- u32 nNew;
- JsonNode *pNew;
- if( pParse->oom ) return -1;
- nNew = pParse->nAlloc*2 + 10;
- pNew = sqlite3_realloc(pParse->aNode, sizeof(JsonNode)*nNew);
- if( pNew==0 ){
- pParse->oom = 1;
- return -1;
- }
- pParse->nAlloc = nNew;
- pParse->aNode = pNew;
+ return jsonParseAddNodeExpand(pParse, eType, n, zContent);
}
p = &pParse->aNode[pParse->nNode];
p->eType = (u8)eType;
@@ -1783,7 +1835,7 @@ static int jsonEachFilter(
jsonEachCursorReset(p);
return SQLITE_NOMEM;
}else{
- JsonNode *pNode;
+ JsonNode *pNode = 0;
if( idxNum==3 ){
const char *zErr = 0;
zRoot = (const char*)sqlite3_value_text(argv[1]);