Skip to content

Commit

Permalink
Fewer mallocs
Browse files Browse the repository at this point in the history
  • Loading branch information
tylerkaraszewski committed Dec 20, 2024
1 parent c8bddad commit 2f6cdab
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 106 deletions.
207 changes: 102 additions & 105 deletions libstuff/sqlite3.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
** separate file. This file contains only code for the core SQLite library.
**
** The content in this amalgamation comes from Fossil check-in
** fa87355f6286be1e92f22a71cbfbfb13d1a4.
** b40cd7395c44b1f2d019d8e809e03de0e083.
*/
#define SQLITE_CORE 1
#define SQLITE_AMALGAMATION 1
Expand Down Expand Up @@ -465,7 +465,7 @@ extern "C" {
*/
#define SQLITE_VERSION "3.47.0"
#define SQLITE_VERSION_NUMBER 3047000
#define SQLITE_SOURCE_ID "2024-12-13 18:13:51 fa87355f6286be1e92f22a71cbfbfb13d1a478d5fb5b38abedbd78bf903171fa"
#define SQLITE_SOURCE_ID "2024-12-20 19:37:41 b40cd7395c44b1f2d019d8e809e03de0e083c93693322a72ddb250a85640528f"

/*
** CAPI3REF: Run-Time Library Version Numbers
Expand Down Expand Up @@ -17859,6 +17859,9 @@ struct Schema {
u8 enc; /* Text encoding used by this database */
u16 schemaFlags; /* Flags associated with this schema */
int cache_size; /* Number of pages to use in the cache */
#ifdef SQLITE_ENABLE_STAT4
void *pStat4Space; /* Memory for stat4 Index.aSample[] arrays */
#endif
};

/*
Expand Down Expand Up @@ -18238,11 +18241,13 @@ struct sqlite3 {
#define SCHEMA_TIME_AFTER_STAT1 12
#define SCHEMA_TIME_AFTER_DEFAULTS 13

#define SCHEMA_TIME_STAT4_Q1_BODY 14
#define SCHEMA_TIME_AFTER_STAT4_Q1 15
#define SCHEMA_TIME_STAT4_Q2_BODY 16
#define SCHEMA_TIME_STAT4_SAMPLE_MALLOC 17
#define SCHEMA_TIME_AFTER_STAT4_Q2 18
#define SCHEMA_TIME_AFTER_STAT4_SPACE 14
#define SCHEMA_TIME_AFTER_STAT4_PREPARE 15

#define SCHEMA_TIME_STAT4_GROWUS 16
#define SCHEMA_TIME_STAT4_Q2_BODYUS 17
#define SCHEMA_TIME_AFTER_STAT4_Q2 18

#define SCHEMA_TIME_AFTER_STAT4 19

#define SCHEMA_TIME_END_ANALYZE_LOAD 20
Expand Down Expand Up @@ -93492,7 +93497,7 @@ SQLITE_PRIVATE void sqlite3CommitTimeLog(u64 *aCommit){
}
zStr = sqlite3_mprintf("%z%s%s%d%s", zStr, (zStr?", ":""),zHash,iVal,zU);
}
sqlite3_log(SQLITE_WARNING, "slow commit (v=19): (%s)", zStr);
sqlite3_log(SQLITE_WARNING, "slow commit (v=20): (%s)", zStr);
sqlite3_free(zStr);
}
}
Expand Down Expand Up @@ -93520,7 +93525,7 @@ SQLITE_PRIVATE void sqlite3PrepareTimeLog(const char *zSql, int nSql, u64 *aPrep
}
if( nByte<0 ){ nByte = sqlite3Strlen30(zSql); }
sqlite3_log(SQLITE_WARNING,
"slow prepare (v=19): (%s) [%.*s]", zStr, nByte, zSql
"slow prepare (v=20): (%s) [%.*s]", zStr, nByte, zSql
);
sqlite3_free(zStr);
}
Expand All @@ -93534,15 +93539,14 @@ SQLITE_PRIVATE void sqlite3SchemaTimeLog(u64 *aSchema, const char *zFile){
for(ii=1; ii<SCHEMA_TIME_N; ii++){
int val = aSchema[ii];
if( val!=0
&& ii!=SCHEMA_TIME_STAT4_Q1_BODY
&& ii!=SCHEMA_TIME_STAT4_Q2_BODY
&& ii!=SCHEMA_TIME_STAT4_SAMPLE_MALLOC
&& ii!=SCHEMA_TIME_STAT4_Q2_BODYUS
&& ii!=SCHEMA_TIME_STAT4_GROWUS
){
val -= i1;
}
zStr = sqlite3_mprintf("%z%s%d", zStr, (zStr?", ":""), val);
}
sqlite3_log(SQLITE_WARNING, "slow schema (%s) (v=19): (%s)", zFile, zStr);
sqlite3_log(SQLITE_WARNING, "slow schema (%s) (v=20): (%s)", zFile, zStr);
sqlite3_free(zStr);
}
}
Expand Down Expand Up @@ -122276,6 +122280,13 @@ static void openStatTable(
# define SQLITE_STAT4_SAMPLES 24
#endif

/*
** Assumed number of of samples when loading sqlite_stat4 data. It doesn't
** matter if there are more or fewer samples than this, but is more efficient
** if this estimate turns out to be true.
*/
#define SQLITE_STAT4_EST_SAMPLES SQLITE_STAT4_SAMPLES

/*
** Three SQL functions - stat_init(), stat_push(), and stat_get() -
** share an instance of the following structure to hold their state
Expand Down Expand Up @@ -123695,7 +123706,9 @@ SQLITE_PRIVATE void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){
IndexSample *p = &pIdx->aSample[j];
sqlite3DbFree(db, p->p);
}
sqlite3DbFree(db, pIdx->aSample);
if( pIdx->nSampleAlloc!=SQLITE_STAT4_EST_SAMPLES ){
sqlite3DbFree(db, pIdx->aSample);
}
}
if( db->pnBytesFreed==0 ){
pIdx->nSample = 0;
Expand Down Expand Up @@ -123789,7 +123802,7 @@ static Index *findIndexOrPrimaryKey(
** Grow the pIdx->aSample[] array. Return SQLITE_OK if successful, or
** SQLITE_NOMEM otherwise.
*/
static int growSampleArray(sqlite3 *db, Index *pIdx){
static int growSampleArray(sqlite3 *db, Index *pIdx, int *piOff){
int nIdxCol = pIdx->nSampleCol;
int nNew = 0;
IndexSample *aNew = 0;
Expand All @@ -123799,31 +123812,24 @@ static int growSampleArray(sqlite3 *db, Index *pIdx){
int i;
u64 t;

/* In production set the initial allocation to SQLITE_STAT4_SAMPLES. This
** means that reallocation will almost never be required. But for debug
** builds, set the initial allocation size to 6 entries so that the
** reallocation code gets tested. todo: use real tests for this. */
assert( pIdx->nSample==pIdx->nSampleAlloc );
#ifdef SQLITE_DEBUG
nNew = 6;
#else
nNew = SQLITE_STAT4_SAMPLES;
#endif
nNew = SQLITE_STAT4_EST_SAMPLES;
if( pIdx->nSample ){
nNew = pIdx->nSample*2;
}

/* Set nByte to the required amount of space */
nByte = ROUND8(sizeof(IndexSample) * nNew);
nByte += sizeof(tRowcnt) * nIdxCol * 3 * nNew;
nByte += nIdxCol * sizeof(tRowcnt); /* Space for Index.aAvgEq[] */

if( db->aSchemaTime ){
t = sqlite3STimeNow();
}
aNew = (IndexSample*)sqlite3DbMallocRaw(db, nByte);
if( aNew==0 ) return SQLITE_NOMEM_BKPT;
if( db->aSchemaTime ){
db->aSchemaTime[SCHEMA_TIME_STAT4_SAMPLE_MALLOC] += (sqlite3STimeNow() - t);
if( nNew==SQLITE_STAT4_EST_SAMPLES ){
aNew = (IndexSample*)&((u8*)pIdx->pSchema->pStat4Space)[*piOff];
*piOff += nByte;
assert( *piOff<=sqlite3_msize(pIdx->pSchema->pStat4Space) );
}else{
aNew = (IndexSample*)sqlite3DbMallocRaw(db, nByte);
if( aNew==0 ) return SQLITE_NOMEM_BKPT;
}

pPtr = (u8*)aNew;
Expand All @@ -123850,15 +123856,53 @@ static int growSampleArray(sqlite3 *db, Index *pIdx){
}
assert( ((u8*)pSpace)-nByte==(u8*)aNew );

sqlite3DbFree(db, pIdx->aSample);
if( pIdx->nSample!=SQLITE_STAT4_EST_SAMPLES ){
sqlite3DbFree(db, pIdx->aSample);
}
pIdx->aSample = aNew;
pIdx->nSampleAlloc = nNew;
return SQLITE_OK;
}

/*
** Load the content from either the sqlite_stat4
** into the relevant Index.aSample[] arrays.
** Allocate the space that will likely be required for the Index.aSample[]
** arrays populated by loading data from the sqlite_stat4 table. Return
** SQLITE_OK if successful, or SQLITE_NOMEM otherwise.
*/
static int stat4AllocSpace(sqlite3 *db, const char *zDb){
int iDb = sqlite3FindDbName(db, zDb);
Schema *pSchema = db->aDb[iDb].pSchema;
int nByte = 0;
HashElem *k;

assert( iDb>=0 );
assert( pSchema->pStat4Space==0 );
for(k=sqliteHashFirst(&pSchema->idxHash); k; k=sqliteHashNext(k)){
Index *pIdx = sqliteHashData(k);
int nIdxCol;
if( !HasRowid(pIdx->pTable) && IsPrimaryKeyIndex(pIdx) ){
nIdxCol = pIdx->nKeyCol;
}else{
nIdxCol = pIdx->nColumn;
}
nByte += ROUND8(sizeof(IndexSample) * SQLITE_STAT4_EST_SAMPLES);
nByte += sizeof(tRowcnt) * nIdxCol * 3 * SQLITE_STAT4_EST_SAMPLES;
nByte += nIdxCol * sizeof(tRowcnt); /* Space for Index.aAvgEq[] */
}

if( nByte>0 ){
pSchema->pStat4Space = sqlite3_malloc(nByte);
if( pSchema->pStat4Space==0 ){
return SQLITE_NOMEM_BKPT;
}
}

return SQLITE_OK;
}

/*
** Load the content from the sqlite_stat4 into the relevant Index.aSample[]
** arrays.
**
** Arguments zSql1 and zSql2 must point to SQL statements that return
** data equivalent to the following:
Expand All @@ -123879,78 +123923,16 @@ static int loadStatTbl(
char *zSql; /* Text of the SQL statement */
Index *pPrevIdx = 0; /* Previous index in the loop */
IndexSample *pSample; /* A slot in pIdx->aSample[] */
int iBlockOff = 0; /* Offset into Schema.pStat4Space */

assert( db->lookaside.bDisable );
#if 0
zSql = sqlite3MPrintf(db, zSql1, zDb);
if( !zSql ){
return SQLITE_NOMEM_BKPT;
}
rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
sqlite3DbFree(db, zSql);
if( rc ) return rc;

while( sqlite3_step(pStmt)==SQLITE_ROW ){
int nIdxCol = 1; /* Number of columns in stat4 records */

char *zIndex; /* Index name */
Index *pIdx; /* Pointer to the index object */
int nSample; /* Number of samples */
int nByte; /* Bytes of space required */
int i; /* Bytes of space required */
tRowcnt *pSpace; /* Available allocated memory space */
u8 *pPtr; /* Available memory as a u8 for easier manipulation */

u64 t = sqlite3STimeNow();

zIndex = (char *)sqlite3_column_text(pStmt, 0);
if( zIndex==0 ) continue;
nSample = sqlite3_column_int(pStmt, 1);
pIdx = findIndexOrPrimaryKey(db, zIndex, zDb);
assert( pIdx==0 || pIdx->nSample==0 );
if( pIdx==0 ) continue;
if( pIdx->aSample!=0 ){
/* The same index appears in sqlite_stat4 under multiple names */
continue;
}
assert( !HasRowid(pIdx->pTable) || pIdx->nColumn==pIdx->nKeyCol+1 );
if( !HasRowid(pIdx->pTable) && IsPrimaryKeyIndex(pIdx) ){
nIdxCol = pIdx->nKeyCol;
}else{
nIdxCol = pIdx->nColumn;
}
pIdx->nSampleCol = nIdxCol;
pIdx->mxSample = nSample;
nByte = ROUND8(sizeof(IndexSample) * nSample);
nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample;
nByte += nIdxCol * sizeof(tRowcnt); /* Space for Index.aAvgEq[] */

pIdx->aSample = sqlite3DbMallocZero(db, nByte);
if( pIdx->aSample==0 ){
sqlite3_finalize(pStmt);
return SQLITE_NOMEM_BKPT;
}
pPtr = (u8*)pIdx->aSample;
pPtr += ROUND8(nSample*sizeof(pIdx->aSample[0]));
pSpace = (tRowcnt*)pPtr;
assert( EIGHT_BYTE_ALIGNMENT( pSpace ) );
pIdx->aAvgEq = pSpace; pSpace += nIdxCol;
pIdx->pTable->tabFlags |= TF_HasStat4;
for(i=0; i<nSample; i++){
pIdx->aSample[i].anEq = pSpace; pSpace += nIdxCol;
pIdx->aSample[i].anLt = pSpace; pSpace += nIdxCol;
pIdx->aSample[i].anDLt = pSpace; pSpace += nIdxCol;
}
assert( ((u8*)pSpace)-nByte==(u8*)(pIdx->aSample) );
if( db->aSchemaTime ){
db->aSchemaTime[SCHEMA_TIME_STAT4_Q1_BODY] += (sqlite3STimeNow() - t);
}
}
rc = sqlite3_finalize(pStmt);
if( rc ) return rc;
#endif
/* Allocate the Schema.pStat4Space block that will be used for the
** Index.aSample[] arrays populated by this call. */
rc = stat4AllocSpace(db, zDb);
if( rc!=SQLITE_OK ) return rc;

sqlite3PrepareTimeSet(db->aSchemaTime, SCHEMA_TIME_AFTER_STAT4_Q1);
sqlite3PrepareTimeSet(db->aSchemaTime, SCHEMA_TIME_AFTER_STAT4_SPACE);

zSql = sqlite3MPrintf(db, zSql2, zDb);
if( !zSql ){
Expand All @@ -123960,6 +123942,8 @@ static int loadStatTbl(
sqlite3DbFree(db, zSql);
if( rc ) return rc;

sqlite3PrepareTimeSet(db->aSchemaTime, SCHEMA_TIME_AFTER_STAT4_PREPARE);

while( sqlite3_step(pStmt)==SQLITE_ROW ){
char *zIndex; /* Index name */
Index *pIdx; /* Pointer to the index object */
Expand All @@ -123972,14 +123956,19 @@ static int loadStatTbl(
if( pIdx==0 ) continue;

if( pIdx->nSample==pIdx->nSampleAlloc ){
u64 t2;
pIdx->pTable->tabFlags |= TF_HasStat4;
assert( !HasRowid(pIdx->pTable) || pIdx->nColumn==pIdx->nKeyCol+1 );
if( !HasRowid(pIdx->pTable) && IsPrimaryKeyIndex(pIdx) ){
pIdx->nSampleCol = pIdx->nKeyCol;
}else{
pIdx->nSampleCol = pIdx->nColumn;
}
if( growSampleArray(db, pIdx) ) break;
t2 = sqlite3STimeNow();
if( growSampleArray(db, pIdx, &iBlockOff) ) break;
if( db->aSchemaTime ){
db->aSchemaTime[SCHEMA_TIME_STAT4_GROWUS] += (sqlite3STimeNow() - t);
}
}

if( pIdx!=pPrevIdx ){
Expand Down Expand Up @@ -124012,7 +124001,7 @@ static int loadStatTbl(
pIdx->nSample++;

if( db->aSchemaTime ){
db->aSchemaTime[SCHEMA_TIME_STAT4_Q2_BODY] += (sqlite3STimeNow() - t);
db->aSchemaTime[SCHEMA_TIME_STAT4_Q2_BODYUS] += (sqlite3STimeNow() - t);
}
}
rc = sqlite3_finalize(pStmt);
Expand Down Expand Up @@ -124089,6 +124078,10 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
pIdx->aSample = 0;
#endif
}
#ifdef SQLITE_ENABLE_STAT4
sqlite3_free(pSchema->pStat4Space);
pSchema->pStat4Space = 0;
#endif

sqlite3PrepareTimeSet(db->aSchemaTime, SCHEMA_TIME_AFTER_CLEAR_STATS);

Expand Down Expand Up @@ -131355,6 +131348,10 @@ SQLITE_PRIVATE void sqlite3SchemaClear(void *p){
pSchema->iGeneration++;
}
pSchema->schemaFlags &= ~(DB_SchemaLoaded|DB_ResetWanted);
#ifdef SQLITE_ENABLE_STAT4
sqlite3_free(pSchema->pStat4Space);
pSchema->pStat4Space = 0;
#endif
}

/*
Expand Down Expand Up @@ -258029,7 +258026,7 @@ static void fts5SourceIdFunc(
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
sqlite3_result_text(pCtx, "fts5: 2024-12-13 18:13:51 fa87355f6286be1e92f22a71cbfbfb13d1a478d5fb5b38abedbd78bf903171fa", -1, SQLITE_TRANSIENT);
sqlite3_result_text(pCtx, "fts5: 2024-12-20 19:37:41 b40cd7395c44b1f2d019d8e809e03de0e083c93693322a72ddb250a85640528f", -1, SQLITE_TRANSIENT);
}

/*
Expand Down
2 changes: 1 addition & 1 deletion libstuff/sqlite3.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ extern "C" {
*/
#define SQLITE_VERSION "3.47.0"
#define SQLITE_VERSION_NUMBER 3047000
#define SQLITE_SOURCE_ID "2024-12-13 18:13:51 fa87355f6286be1e92f22a71cbfbfb13d1a478d5fb5b38abedbd78bf903171fa"
#define SQLITE_SOURCE_ID "2024-12-20 19:37:41 b40cd7395c44b1f2d019d8e809e03de0e083c93693322a72ddb250a85640528f"

/*
** CAPI3REF: Run-Time Library Version Numbers
Expand Down

0 comments on commit 2f6cdab

Please sign in to comment.