mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-03 16:53:36 +03:00
Small simplification to the prepare statement opcode memory reuse logic.
Easier to read, and slightly smaller and faster. FossilOrigin-Name: 8a1deae497edf3fa43fa96152d140405398c5ed6
This commit is contained in:
12
manifest
12
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Small\ssimplification\sand\sperformance\simprovement\sin\smemsys5Free().
|
C Small\ssimplification\sto\sthe\sprepare\sstatement\sopcode\smemory\sreuse\slogic.\nEasier\sto\sread,\sand\sslightly\ssmaller\sand\sfaster.
|
||||||
D 2016-01-25T01:07:59.493
|
D 2016-01-25T02:15:02.255
|
||||||
F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4
|
F Makefile.in 027c1603f255390c43a426671055a31c0a65fdb4
|
||||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||||
F Makefile.msc 1708a78eda223b6daa302b140037fcc214a779f9
|
F Makefile.msc 1708a78eda223b6daa302b140037fcc214a779f9
|
||||||
@@ -414,7 +414,7 @@ F src/vdbe.c b90d9d38e5e0260c2eafa3cb4c2274d8ea94da27
|
|||||||
F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337
|
F src/vdbe.h 7a733ea8aac1b77305a67698e784fa3484ee3337
|
||||||
F src/vdbeInt.h 42eefa4f9e7432b9968d321b44e48821ec13b189
|
F src/vdbeInt.h 42eefa4f9e7432b9968d321b44e48821ec13b189
|
||||||
F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e
|
F src/vdbeapi.c ffae8f5af4570fbd548504e815e9fb7227f0822e
|
||||||
F src/vdbeaux.c 07f8f485a6cbc0a62da660f14e303061d45d5cb6
|
F src/vdbeaux.c 757f86e6fef8efb3dd4226cb31e2e82b9c44c883
|
||||||
F src/vdbeblob.c 37c3d11a753e403698c69e17383d282e1ae73e75
|
F src/vdbeblob.c 37c3d11a753e403698c69e17383d282e1ae73e75
|
||||||
F src/vdbemem.c b9181e77eca2a095929d46250daf85c8d2621fc0
|
F src/vdbemem.c b9181e77eca2a095929d46250daf85c8d2621fc0
|
||||||
F src/vdbesort.c 0971557e5d3c289e46f56a52aed2197c13251de7
|
F src/vdbesort.c 0971557e5d3c289e46f56a52aed2197c13251de7
|
||||||
@@ -1419,7 +1419,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
|
|||||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||||
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
|
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
|
||||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||||
P dd0100dd87e2c7c70fabb2d3188f0906e605583d
|
P 0a9cff5c4822874b74e90bfca3963bc7e5c753a5
|
||||||
R a179bcf25d5e17fae98e7434f7b5c754
|
R 5ad29c29cc49b0c7f9cd0947deba5a80
|
||||||
U drh
|
U drh
|
||||||
Z 6a3ae2a8bc97ab052cdf4e5d8140159f
|
Z 5c673e5ee459b55b04084dc37cebc110
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
0a9cff5c4822874b74e90bfca3963bc7e5c753a5
|
8a1deae497edf3fa43fa96152d140405398c5ed6
|
||||||
119
src/vdbeaux.c
119
src/vdbeaux.c
@@ -1721,41 +1721,43 @@ void sqlite3VdbeIOTraceSql(Vdbe *p){
|
|||||||
}
|
}
|
||||||
#endif /* !SQLITE_OMIT_TRACE && SQLITE_ENABLE_IOTRACE */
|
#endif /* !SQLITE_OMIT_TRACE && SQLITE_ENABLE_IOTRACE */
|
||||||
|
|
||||||
/*
|
/* An instance of this object describes bulk memory available for use
|
||||||
** Allocate space from a fixed size buffer and return a pointer to
|
** by subcomponents of a prepared statement. Space is allocated out
|
||||||
** that space. If insufficient space is available, return NULL.
|
** of a ReusableSpace object by the allocSpace() routine below.
|
||||||
|
*/
|
||||||
|
struct ReusableSpace {
|
||||||
|
u8 *pSpace; /* Available memory */
|
||||||
|
int nFree; /* Bytes of available memory */
|
||||||
|
int nNeeded; /* Total bytes that could not be allocated */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Try to allocate nByte bytes of 8-byte aligned bulk memory for pBuf
|
||||||
|
** from the ReusableSpace object. Return a pointer to the allocated
|
||||||
|
** memory on success. If insufficient memory is available in the
|
||||||
|
** ReusableSpace object, increase the ReusableSpace.nNeeded
|
||||||
|
** value by the amount needed and return NULL.
|
||||||
**
|
**
|
||||||
** The pBuf parameter is the initial value of a pointer which will
|
** If pBuf is not initially NULL, that means that the memory has already
|
||||||
** receive the new memory. pBuf is normally NULL. If pBuf is not
|
** been allocated by a prior call to this routine, so just return a copy
|
||||||
** NULL, it means that memory space has already been allocated and that
|
** of pBuf and leave ReusableSpace unchanged.
|
||||||
** this routine should not allocate any new memory. When pBuf is not
|
|
||||||
** NULL simply return pBuf. Only allocate new memory space when pBuf
|
|
||||||
** is NULL.
|
|
||||||
**
|
**
|
||||||
** nByte is the number of bytes of space needed.
|
** This allocator is employed to repurpose unused slots at the end of the
|
||||||
**
|
** opcode array of prepared state for other memory needs of the prepared
|
||||||
** pFrom points to *pnFrom bytes of available space. New space is allocated
|
** statement.
|
||||||
** from the end of the pFrom buffer and *pnFrom is decremented.
|
|
||||||
**
|
|
||||||
** *pnNeeded is a counter of the number of bytes of space that have failed
|
|
||||||
** to allocate. If there is insufficient space in pFrom to satisfy the
|
|
||||||
** request, then increment *pnNeeded by the amount of the request.
|
|
||||||
*/
|
*/
|
||||||
static void *allocSpace(
|
static void *allocSpace(
|
||||||
void *pBuf, /* Where return pointer will be stored */
|
struct ReusableSpace *p, /* Bulk memory available for allocation */
|
||||||
int nByte, /* Number of bytes to allocate */
|
void *pBuf, /* Pointer to a prior allocation */
|
||||||
u8 *pFrom, /* Memory available for allocation */
|
int nByte /* Bytes of memory needed */
|
||||||
int *pnFrom, /* IN/OUT: Space available at pFrom */
|
|
||||||
int *pnNeeded /* If allocation cannot be made, increment *pnByte */
|
|
||||||
){
|
){
|
||||||
assert( EIGHT_BYTE_ALIGNMENT(pFrom) );
|
assert( EIGHT_BYTE_ALIGNMENT(p->pSpace) );
|
||||||
if( pBuf==0 ){
|
if( pBuf==0 ){
|
||||||
nByte = ROUND8(nByte);
|
nByte = ROUND8(nByte);
|
||||||
if( nByte <= *pnFrom ){
|
if( nByte <= p->nFree ){
|
||||||
*pnFrom -= nByte;
|
p->nFree -= nByte;
|
||||||
pBuf = &pFrom[*pnFrom];
|
pBuf = &p->pSpace[p->nFree];
|
||||||
}else{
|
}else{
|
||||||
*pnNeeded += nByte;
|
p->nNeeded += nByte;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert( EIGHT_BYTE_ALIGNMENT(pBuf) );
|
assert( EIGHT_BYTE_ALIGNMENT(pBuf) );
|
||||||
@@ -1831,9 +1833,7 @@ void sqlite3VdbeMakeReady(
|
|||||||
int nArg; /* Number of arguments in subprograms */
|
int nArg; /* Number of arguments in subprograms */
|
||||||
int nOnce; /* Number of OP_Once instructions */
|
int nOnce; /* Number of OP_Once instructions */
|
||||||
int n; /* Loop counter */
|
int n; /* Loop counter */
|
||||||
int nFree; /* Available free space */
|
struct ReusableSpace x; /* Reusable bulk memory */
|
||||||
u8 *zCsr; /* Memory available for allocation */
|
|
||||||
int nByte; /* How much extra memory is needed */
|
|
||||||
|
|
||||||
assert( p!=0 );
|
assert( p!=0 );
|
||||||
assert( p->nOp>0 );
|
assert( p->nOp>0 );
|
||||||
@@ -1851,7 +1851,7 @@ void sqlite3VdbeMakeReady(
|
|||||||
|
|
||||||
/* For each cursor required, also allocate a memory cell. Memory
|
/* For each cursor required, also allocate a memory cell. Memory
|
||||||
** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by
|
** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by
|
||||||
** the vdbe program. Instead they are used to allocate space for
|
** the vdbe program. Instead they are used to allocate memory for
|
||||||
** VdbeCursor/BtCursor structures. The blob of memory associated with
|
** VdbeCursor/BtCursor structures. The blob of memory associated with
|
||||||
** cursor 0 is stored in memory cell nMem. Memory cell (nMem-1)
|
** cursor 0 is stored in memory cell nMem. Memory cell (nMem-1)
|
||||||
** stores the blob of memory associated with cursor 1, etc.
|
** stores the blob of memory associated with cursor 1, etc.
|
||||||
@@ -1860,20 +1860,18 @@ void sqlite3VdbeMakeReady(
|
|||||||
*/
|
*/
|
||||||
nMem += nCursor;
|
nMem += nCursor;
|
||||||
|
|
||||||
/* zCsr will initially point to nFree bytes of unused space at the
|
/* Figure out how much reusable memory is available at the end of the
|
||||||
** end of the opcode array, p->aOp. The computation of nFree is
|
** opcode array. This extra memory will be reallocated for other elements
|
||||||
** conservative - it might be smaller than the true number of free
|
** of the prepared statement.
|
||||||
** bytes, but never larger. nFree must be a multiple of 8 - it is
|
|
||||||
** rounded down if is not.
|
|
||||||
*/
|
*/
|
||||||
n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode space used */
|
n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */
|
||||||
zCsr = &((u8*)p->aOp)[n]; /* Unused opcode space */
|
x.pSpace = &((u8*)p->aOp)[n]; /* Unused opcode memory */
|
||||||
assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
|
assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) );
|
||||||
nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused space */
|
x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */
|
||||||
assert( nFree>=0 );
|
assert( x.nFree>=0 );
|
||||||
if( nFree>0 ){
|
if( x.nFree>0 ){
|
||||||
memset(zCsr, 0, nFree);
|
memset(x.pSpace, 0, x.nFree);
|
||||||
assert( EIGHT_BYTE_ALIGNMENT(&zCsr[nFree]) );
|
assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) );
|
||||||
}
|
}
|
||||||
|
|
||||||
resolveP2Values(p, &nArg);
|
resolveP2Values(p, &nArg);
|
||||||
@@ -1883,33 +1881,30 @@ void sqlite3VdbeMakeReady(
|
|||||||
}
|
}
|
||||||
p->expired = 0;
|
p->expired = 0;
|
||||||
|
|
||||||
/* Memory for registers, parameters, cursor, etc, is allocated in two
|
/* Memory for registers, parameters, cursor, etc, is allocated in one or two
|
||||||
** passes. On the first pass, we try to reuse unused space at the
|
** passes. On the first pass, we try to reuse unused memory at the
|
||||||
** end of the opcode array. If we are unable to satisfy all memory
|
** end of the opcode array. If we are unable to satisfy all memory
|
||||||
** requirements by reusing the opcode array tail, then the second
|
** requirements by reusing the opcode array tail, then the second
|
||||||
** pass will fill in the rest using a fresh allocation.
|
** pass will fill in the remainder using a fresh memory allocation.
|
||||||
**
|
**
|
||||||
** This two-pass approach that reuses as much memory as possible from
|
** This two-pass approach that reuses as much memory as possible from
|
||||||
** the leftover space at the end of the opcode array can significantly
|
** the leftover memory at the end of the opcode array. This can significantly
|
||||||
** reduce the amount of memory held by a prepared statement.
|
** reduce the amount of memory held by a prepared statement.
|
||||||
*/
|
*/
|
||||||
do {
|
do {
|
||||||
nByte = 0;
|
x.nNeeded = 0;
|
||||||
p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), zCsr, &nFree, &nByte);
|
p->aMem = allocSpace(&x, p->aMem, nMem*sizeof(Mem));
|
||||||
p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), zCsr, &nFree, &nByte);
|
p->aVar = allocSpace(&x, p->aVar, nVar*sizeof(Mem));
|
||||||
p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), zCsr, &nFree, &nByte);
|
p->apArg = allocSpace(&x, p->apArg, nArg*sizeof(Mem*));
|
||||||
p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*),
|
p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*));
|
||||||
zCsr, &nFree, &nByte);
|
p->aOnceFlag = allocSpace(&x, p->aOnceFlag, nOnce);
|
||||||
p->aOnceFlag = allocSpace(p->aOnceFlag, nOnce, zCsr, &nFree, &nByte);
|
|
||||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||||
p->anExec = allocSpace(p->anExec, p->nOp*sizeof(i64), zCsr, &nFree, &nByte);
|
p->anExec = allocSpace(&x, p->anExec, p->nOp*sizeof(i64));
|
||||||
#endif
|
#endif
|
||||||
if( nByte ){
|
if( x.nNeeded==0 ) break;
|
||||||
p->pFree = sqlite3DbMallocZero(db, nByte);
|
x.pSpace = p->pFree = sqlite3DbMallocZero(db, x.nNeeded);
|
||||||
}
|
x.nFree = x.nNeeded;
|
||||||
zCsr = p->pFree;
|
}while( !db->mallocFailed );
|
||||||
nFree = nByte;
|
|
||||||
}while( nByte && !db->mallocFailed );
|
|
||||||
|
|
||||||
p->nCursor = nCursor;
|
p->nCursor = nCursor;
|
||||||
p->nOnceFlag = nOnce;
|
p->nOnceFlag = nOnce;
|
||||||
|
|||||||
Reference in New Issue
Block a user