/ Check-in [48ecf187]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Simplify and improve the performance of the sqlite3VdbeMemGrow() routine.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 48ecf18774ba9572d86696c60d87007a619d9f53
User & Date: drh 2013-12-10 19:49:00
Context
2013-12-10
20:53
In the OP_MakeRecord opcode, factor out affinity changes into separate loop, for a slight performance advantage. check-in: 1c6ee9b8 user: drh tags: trunk
19:49
Simplify and improve the performance of the sqlite3VdbeMemGrow() routine. check-in: 48ecf187 user: drh tags: trunk
2013-12-09
23:17
Simplifications to the OP_MakeRecord opcode and the sqlite3VdbeSerialPut() helper function. check-in: 7277a769 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/main.c.

   584    584         db->lookaside.pFree = p;
   585    585         p = (LookasideSlot*)&((u8*)p)[sz];
   586    586       }
   587    587       db->lookaside.pEnd = p;
   588    588       db->lookaside.bEnabled = 1;
   589    589       db->lookaside.bMalloced = pBuf==0 ?1:0;
   590    590     }else{
   591         -    db->lookaside.pEnd = 0;
          591  +    db->lookaside.pStart = db;
          592  +    db->lookaside.pEnd = db;
   592    593       db->lookaside.bEnabled = 0;
   593    594       db->lookaside.bMalloced = 0;
   594    595     }
   595    596     return SQLITE_OK;
   596    597   }
   597    598   
   598    599   /*

Changes to src/malloc.c.

   429    429   }
   430    430   
   431    431   /*
   432    432   ** TRUE if p is a lookaside memory allocation from db
   433    433   */
   434    434   #ifndef SQLITE_OMIT_LOOKASIDE
   435    435   static int isLookaside(sqlite3 *db, void *p){
   436         -  return p && p>=db->lookaside.pStart && p<db->lookaside.pEnd;
          436  +  return p>=db->lookaside.pStart && p<db->lookaside.pEnd;
   437    437   }
   438    438   #else
   439    439   #define isLookaside(A,B) 0
   440    440   #endif
   441    441   
   442    442   /*
   443    443   ** Return the size of a memory allocation previously obtained from
................................................................................
   445    445   */
   446    446   int sqlite3MallocSize(void *p){
   447    447     assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
   448    448     assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) );
   449    449     return sqlite3GlobalConfig.m.xSize(p);
   450    450   }
   451    451   int sqlite3DbMallocSize(sqlite3 *db, void *p){
   452         -  assert( db==0 || sqlite3_mutex_held(db->mutex) );
   453         -  if( db && isLookaside(db, p) ){
          452  +  assert( db!=0 );
          453  +  assert( sqlite3_mutex_held(db->mutex) );
          454  +  if( isLookaside(db, p) ){
   454    455       return db->lookaside.sz;
   455    456     }else{
   456    457       assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
   457    458       assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
   458    459       assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
   459    460       return sqlite3GlobalConfig.m.xSize(p);
   460    461     }

Changes to src/vdbemem.c.

    55     55     assert(rc==SQLITE_NOMEM || pMem->enc==desiredEnc);
    56     56     return rc;
    57     57   #endif
    58     58   }
    59     59   
    60     60   /*
    61     61   ** Make sure pMem->z points to a writable allocation of at least 
    62         -** n bytes.
           62  +** min(n,32) bytes.
    63     63   **
    64         -** If the third argument passed to this function is true, then memory
    65         -** cell pMem must contain a string or blob. In this case the content is
    66         -** preserved. Otherwise, if the third parameter to this function is false,
    67         -** any current string or blob value may be discarded.
    68         -**
    69         -** This function sets the MEM_Dyn flag and clears any xDel callback.
    70         -** It also clears MEM_Ephem and MEM_Static. If the preserve flag is 
    71         -** not set, Mem.n is zeroed.
           64  +** If the bPreserve argument is true, then copy of the content of
           65  +** pMem->z into the new allocation.  pMem must be either a string or
           66  +** blob if bPreserve is true.  If bPreserve is false, any prior content
           67  +** in pMem->z is discarded.
    72     68   */
    73         -int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){
           69  +int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
    74     70     assert( 1 >=
    75     71       ((pMem->zMalloc && pMem->zMalloc==pMem->z) ? 1 : 0) +
    76     72       (((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) + 
    77     73       ((pMem->flags&MEM_Ephem) ? 1 : 0) + 
    78     74       ((pMem->flags&MEM_Static) ? 1 : 0)
    79     75     );
    80     76     assert( (pMem->flags&MEM_RowSet)==0 );
    81     77   
    82         -  /* If the preserve flag is set to true, then the memory cell must already
           78  +  /* If the bPreserve flag is set to true, then the memory cell must already
    83     79     ** contain a valid string or blob value.  */
    84         -  assert( preserve==0 || pMem->flags&(MEM_Blob|MEM_Str) );
           80  +  assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) );
           81  +  testcase( bPreserve && pMem->z==0 );
    85     82   
    86         -  if( n<32 ) n = 32;
    87         -  if( sqlite3DbMallocSize(pMem->db, pMem->zMalloc)<n ){
    88         -    if( preserve && pMem->z==pMem->zMalloc ){
           83  +  if( pMem->zMalloc==0 || sqlite3DbMallocSize(pMem->db, pMem->zMalloc)<n ){
           84  +    if( n<32 ) n = 32;
           85  +    if( bPreserve && pMem->z==pMem->zMalloc ){
    89     86         pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
    90         -      preserve = 0;
           87  +      bPreserve = 0;
    91     88       }else{
    92     89         sqlite3DbFree(pMem->db, pMem->zMalloc);
    93     90         pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
    94     91       }
           92  +    if( pMem->zMalloc==0 ){
           93  +      sqlite3VdbeMemRelease(pMem);
           94  +      pMem->flags = MEM_Null;  
           95  +      return SQLITE_NOMEM;
           96  +    }
    95     97     }
    96     98   
    97         -  if( pMem->z && preserve && pMem->zMalloc && pMem->z!=pMem->zMalloc ){
           99  +  if( pMem->z && bPreserve && pMem->z!=pMem->zMalloc ){
    98    100       memcpy(pMem->zMalloc, pMem->z, pMem->n);
    99    101     }
   100         -  if( pMem->flags&MEM_Dyn && pMem->xDel ){
          102  +  if( (pMem->flags&MEM_Dyn)!=0 && pMem->xDel ){
   101    103       assert( pMem->xDel!=SQLITE_DYNAMIC );
   102    104       pMem->xDel((void *)(pMem->z));
   103    105     }
   104    106   
   105    107     pMem->z = pMem->zMalloc;
   106         -  if( pMem->z==0 ){
   107         -    pMem->flags = MEM_Null;
   108         -  }else{
   109         -    pMem->flags &= ~(MEM_Ephem|MEM_Static);
   110         -  }
          108  +  pMem->flags &= ~(MEM_Ephem|MEM_Static);
   111    109     pMem->xDel = 0;
   112         -  return (pMem->z ? SQLITE_OK : SQLITE_NOMEM);
          110  +  return SQLITE_OK;
   113    111   }
   114    112   
   115    113   /*
   116    114   ** Make the given Mem object MEM_Dyn.  In other words, make it so
   117    115   ** that any TEXT or BLOB content is stored in memory obtained from
   118    116   ** malloc().  In this way, we know that the memory is safe to be
   119    117   ** overwritten or altered.