diff options
author | drh <drh@noemail.net> | 2015-09-24 01:06:37 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2015-09-24 01:06:37 +0000 |
commit | 9567794fd931511bff5bcff1fe4c2749a28b65a4 (patch) | |
tree | 03f1e071349fc8f097f867ad8ce8cad728a2f31f /ext/misc/json1.c | |
parent | 58cb6dbe0d9d32386a61fba1812dfbacc594aa46 (diff) | |
download | sqlite-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.c | 78 |
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]); |