/ Check-in [7dd4b07a]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Performance optimizations on the JSON parser.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:7dd4b07a42eb84589d34430b9d7bfa88fbd743eb
User & Date: drh 2015-09-24 01:06:37
Context
2015-09-24
01:40
Another (smaller) performance optimization for the JSON parser. check-in: c43daa8c user: drh tags: trunk
01:06
Performance optimizations on the JSON parser. check-in: 7dd4b07a user: drh tags: trunk
2015-09-23
19:17
Take care that the number of reserved bits per page is consistent between the source and destination databases when doing the back-copy on a VACUUM. check-in: 5b61b72f user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/misc/json1.c.

    33     33   
    34     34   #define UNUSED_PARAM(X)  (void)(X)
    35     35   
    36     36   /*
    37     37   ** Versions of isspace(), isalnum() and isdigit() to which it is safe
    38     38   ** to pass signed char values.
    39     39   */
    40         -#define safe_isspace(x) isspace((unsigned char)(x))
    41     40   #define safe_isdigit(x) isdigit((unsigned char)(x))
    42     41   #define safe_isalnum(x) isalnum((unsigned char)(x))
    43     42   
           43  +/*
           44  +** Growing our own isspace() routine this way is twice as fast as
           45  +** the library isspace() function, resulting in a 7% overall performance
           46  +** increase for the parser.  (Ubuntu14.10 gcc 4.8.4 x64 with -Os).
           47  +*/
           48  +static const char jsonIsSpace[] = {
           49  +  0, 0, 0, 0, 0, 0, 0, 0,     0, 1, 1, 0, 1, 1, 0, 0,
           50  +  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
           51  +  1, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
           52  +  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
           53  +  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
           54  +  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
           55  +  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
           56  +  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
           57  +  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
           58  +  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
           59  +  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
           60  +  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
           61  +  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
           62  +  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
           63  +  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
           64  +  0, 0, 0, 0, 0, 0, 0, 0,     0, 0, 0, 0, 0, 0, 0, 0,
           65  +};
           66  +#define safe_isspace(x) (jsonIsSpace[(unsigned char)x])
           67  +
    44     68   /* Unsigned integer types */
    45     69   typedef sqlite3_uint64 u64;
    46     70   typedef unsigned int u32;
    47     71   typedef unsigned char u8;
    48     72   
    49     73   /* Objects */
    50     74   typedef struct JsonString JsonString;
................................................................................
   543    567       case JSON_ARRAY:
   544    568       case JSON_OBJECT: {
   545    569         jsonReturnJson(pNode, pCtx, aReplace);
   546    570         break;
   547    571       }
   548    572     }
   549    573   }
          574  +
          575  +/* Forward reference */
          576  +static int jsonParseAddNode(JsonParse*,u32,u32,const char*);
          577  +
          578  +/*
          579  +** A macro to hint to the compiler that a function should not be
          580  +** inlined.
          581  +*/
          582  +#if defined(__GNUC__)
          583  +#  define JSON_NOINLINE  __attribute__((noinline))
          584  +#elif defined(_MSC_VER) && _MSC_VER>=1310
          585  +#  define JSON_NOINLINE  __declspec(noinline)
          586  +#else
          587  +#  define JSON_NOINLINE
          588  +#endif
          589  +
          590  +
          591  +static JSON_NOINLINE int jsonParseAddNodeExpand(
          592  +  JsonParse *pParse,        /* Append the node to this object */
          593  +  u32 eType,                /* Node type */
          594  +  u32 n,                    /* Content size or sub-node count */
          595  +  const char *zContent      /* Content */
          596  +){
          597  +  u32 nNew;
          598  +  JsonNode *pNew;
          599  +  assert( pParse->nNode>=pParse->nAlloc );
          600  +  if( pParse->oom ) return -1;
          601  +  nNew = pParse->nAlloc*2 + 10;
          602  +  pNew = sqlite3_realloc(pParse->aNode, sizeof(JsonNode)*nNew);
          603  +  if( pNew==0 ){
          604  +    pParse->oom = 1;
          605  +    return -1;
          606  +  }
          607  +  pParse->nAlloc = nNew;
          608  +  pParse->aNode = pNew;
          609  +  assert( pParse->nNode<pParse->nAlloc );
          610  +  return jsonParseAddNode(pParse, eType, n, zContent);
          611  +}
   550    612   
   551    613   /*
   552    614   ** Create a new JsonNode instance based on the arguments and append that
   553    615   ** instance to the JsonParse.  Return the index in pParse->aNode[] of the
   554    616   ** new node, or -1 if a memory allocation fails.
   555    617   */
   556    618   static int jsonParseAddNode(
................................................................................
   557    619     JsonParse *pParse,        /* Append the node to this object */
   558    620     u32 eType,                /* Node type */
   559    621     u32 n,                    /* Content size or sub-node count */
   560    622     const char *zContent      /* Content */
   561    623   ){
   562    624     JsonNode *p;
   563    625     if( pParse->nNode>=pParse->nAlloc ){
   564         -    u32 nNew;
   565         -    JsonNode *pNew;
   566         -    if( pParse->oom ) return -1;
   567         -    nNew = pParse->nAlloc*2 + 10;
   568         -    pNew = sqlite3_realloc(pParse->aNode, sizeof(JsonNode)*nNew);
   569         -    if( pNew==0 ){
   570         -      pParse->oom = 1;
   571         -      return -1;
   572         -    }
   573         -    pParse->nAlloc = nNew;
   574         -    pParse->aNode = pNew;
          626  +    return jsonParseAddNodeExpand(pParse, eType, n, zContent);
   575    627     }
   576    628     p = &pParse->aNode[pParse->nNode];
   577    629     p->eType = (u8)eType;
   578    630     p->jnFlags = 0;
   579    631     p->iVal = 0;
   580    632     p->n = n;
   581    633     p->u.zJContent = zContent;
................................................................................
  1779   1831       }
  1780   1832       jsonEachCursorReset(p);
  1781   1833       return rc;
  1782   1834     }else if( p->bRecursive && jsonParseFindParents(&p->sParse) ){
  1783   1835       jsonEachCursorReset(p);
  1784   1836       return SQLITE_NOMEM;
  1785   1837     }else{
  1786         -    JsonNode *pNode;
         1838  +    JsonNode *pNode = 0;
  1787   1839       if( idxNum==3 ){
  1788   1840         const char *zErr = 0;
  1789   1841         zRoot = (const char*)sqlite3_value_text(argv[1]);
  1790   1842         if( zRoot==0 ) return SQLITE_OK;
  1791   1843         n = sqlite3_value_bytes(argv[1]);
  1792   1844         p->zRoot = sqlite3_malloc64( n+1 );
  1793   1845         if( p->zRoot==0 ) return SQLITE_NOMEM;