Skip to content

Commit 4093b29

Browse files
author
drh
committed
Convert the JSON functions to use lookaside memory allocation whenever
feasible, to avoid hitting the global memory allocator mutex. FossilOrigin-Name: a79a244954f728596da3c0e28fa3b887258d1bd831f53881970f418f3fba84c7
1 parent 433e904 commit 4093b29

3 files changed

Lines changed: 34 additions & 24 deletions

File tree

manifest

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
C Change\sa\sconstant\sfrom\sdecimal\sto\shex\sto\savoid\sa\scompiler\swarning\son\sMac.
2-
D 2024-01-03T15:49:04.315
1+
C Convert\sthe\sJSON\sfunctions\sto\suse\slookaside\smemory\sallocation\swhenever\nfeasible,\sto\savoid\shitting\sthe\sglobal\smemory\sallocator\smutex.
2+
D 2024-01-03T16:41:50.573
33
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
44
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
55
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -697,7 +697,7 @@ F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
697697
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
698698
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
699699
F src/insert.c 3f0a94082d978bbdd33c38fefea15346c6c6bffb70bc645a71dc0f1f87dd3276
700-
F src/json.c a84de35816b8aebf6a97e08887cce486c0591d0b6147088fa888325f0c17f9ef
700+
F src/json.c 4913fd22c4f0fa30643afb93a4d78d289cd490620e782b31016c3d4b2049b1cc
701701
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
702702
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
703703
F src/main.c ce714ee501122c76eb2e69b292bebe443aba611fc3b88e6786eb910285515fe4
@@ -2156,8 +2156,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
21562156
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
21572157
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
21582158
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
2159-
P 769de0b98e136e4a0945b80216d0c9583c1ccd9de69cb0494875c2300e172646
2160-
R e916baf59c351e9547549cf9c20af1c2
2159+
P e3acb8a43ad544fd5b5341058276bd3b61b6bdb6b719790476a90e0de4320f90
2160+
R 951d215a027ca002df153a3678fabcb5
21612161
U drh
2162-
Z 9cefdf7e48b570cbd02d35dc60bf134c
2162+
Z 4bd172c52ecc91bae1ff8ea6834cc34c
21632163
# Remove this line to create a well-formed Fossil manifest.

manifest.uuid

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
e3acb8a43ad544fd5b5341058276bd3b61b6bdb6b719790476a90e0de4320f90
1+
a79a244954f728596da3c0e28fa3b887258d1bd831f53881970f418f3fba84c7

src/json.c

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ struct JsonParse {
298298
u32 nBlob; /* Bytes of aBlob[] actually used */
299299
u32 nBlobAlloc; /* Bytes allocated to aBlob[]. 0 if aBlob is external */
300300
char *zJson; /* Json text used for parsing */
301+
sqlite3 *db; /* The database connection to which this object belongs */
301302
int nJson; /* Length of the zJson string in bytes */
302303
u32 nJPRef; /* Number of references to this object */
303304
u32 iErr; /* Error location in zJson[] */
@@ -823,7 +824,7 @@ static void jsonParseReset(JsonParse *pParse){
823824
pParse->bJsonIsRCStr = 0;
824825
}
825826
if( pParse->nBlobAlloc ){
826-
sqlite3_free(pParse->aBlob);
827+
sqlite3DbFree(pParse->db, pParse->aBlob);
827828
pParse->aBlob = 0;
828829
pParse->nBlob = 0;
829830
pParse->nBlobAlloc = 0;
@@ -840,7 +841,7 @@ static void jsonParseFree(JsonParse *pParse){
840841
pParse->nJPRef--;
841842
}else{
842843
jsonParseReset(pParse);
843-
sqlite3_free(pParse);
844+
sqlite3DbFree(pParse->db, pParse);
844845
}
845846
}
846847
}
@@ -1071,7 +1072,7 @@ static int jsonBlobExpand(JsonParse *pParse, u32 N){
10711072
t = pParse->nBlobAlloc*2;
10721073
}
10731074
if( t<N ) t = N+100;
1074-
aNew = sqlite3_realloc64( pParse->aBlob, t );
1075+
aNew = sqlite3DbRealloc(pParse->db, pParse->aBlob, t);
10751076
if( aNew==0 ){ pParse->oom = 1; return 1; }
10761077
pParse->aBlob = aNew;
10771078
pParse->nBlobAlloc = t;
@@ -1996,14 +1997,15 @@ static void jsonReturnStringAsBlob(JsonString *pStr){
19961997
jsonStringTerminate(pStr);
19971998
px.zJson = pStr->zBuf;
19981999
px.nJson = pStr->nUsed;
2000+
px.db = sqlite3_context_db_handle(pStr->pCtx);
19992001
(void)jsonTranslateTextToBlob(&px, 0);
20002002
if( px.oom ){
2001-
sqlite3_free(px.aBlob);
2003+
sqlite3DbFree(px.db, px.aBlob);
20022004
sqlite3_result_error_nomem(pStr->pCtx);
20032005
}else{
20042006
assert( px.nBlobAlloc>0 );
20052007
assert( !px.bReadOnly );
2006-
sqlite3_result_blob(pStr->pCtx, px.aBlob, px.nBlob, sqlite3_free);
2008+
sqlite3_result_blob(pStr->pCtx, px.aBlob, px.nBlob, SQLITE_DYNAMIC);
20072009
}
20082010
}
20092011

@@ -2619,6 +2621,7 @@ static u32 jsonCreateEditSubstructure(
26192621
static const u8 emptyObject[] = { JSONB_ARRAY, JSONB_OBJECT };
26202622
int rc;
26212623
memset(pIns, 0, sizeof(*pIns));
2624+
pIns->db = pParse->db;
26222625
if( zTail[0]==0 ){
26232626
/* No substructure. Just insert what is given in pParse. */
26242627
pIns->aBlob = pParse->aIns;
@@ -2746,6 +2749,7 @@ static u32 jsonLookupStep(
27462749
testcase( pParse->eEdit==JEDIT_INS );
27472750
testcase( pParse->eEdit==JEDIT_SET );
27482751
memset(&ix, 0, sizeof(ix));
2752+
ix.db = pParse->db;
27492753
jsonBlobAppendNode(&ix, rawKey?JSONB_TEXTRAW:JSONB_TEXT5, nKey, 0);
27502754
pParse->oom |= ix.oom;
27512755
rc = jsonCreateEditSubstructure(pParse, &v, &zPath[i]);
@@ -2956,7 +2960,7 @@ static void jsonReturnFromBlob(
29562960
char *zOut;
29572961
u32 nOut = sz;
29582962
z = (const char*)&pParse->aBlob[i+n];
2959-
zOut = sqlite3_malloc( nOut+1 );
2963+
zOut = sqlite3DbMallocRaw(db, nOut+1);
29602964
if( zOut==0 ) goto returnfromblob_oom;
29612965
for(iIn=iOut=0; iIn<sz; iIn++){
29622966
char c = z[iIn];
@@ -2990,7 +2994,7 @@ static void jsonReturnFromBlob(
29902994
} /* end for() */
29912995
assert( iOut<=nOut );
29922996
zOut[iOut] = 0;
2993-
sqlite3_result_text(pCtx, zOut, iOut, sqlite3_free);
2997+
sqlite3_result_text(pCtx, zOut, iOut, SQLITE_DYNAMIC);
29942998
break;
29952999
}
29963000
case JSONB_ARRAY:
@@ -3043,6 +3047,7 @@ static int jsonFunctionArgToBlob(
30433047
int eType = sqlite3_value_type(pArg);
30443048
static u8 aNull[] = { 0x00 };
30453049
memset(pParse, 0, sizeof(pParse[0]));
3050+
pParse->db = sqlite3_context_db_handle(ctx);
30463051
switch( eType ){
30473052
default: {
30483053
pParse->aBlob = aNull;
@@ -3068,7 +3073,7 @@ static int jsonFunctionArgToBlob(
30683073
pParse->nJson = nJson;
30693074
if( jsonConvertTextToBlob(pParse, ctx) ){
30703075
sqlite3_result_error(ctx, "malformed JSON", -1);
3071-
sqlite3_free(pParse->aBlob);
3076+
sqlite3DbFree(pParse->db, pParse->aBlob);
30723077
memset(pParse, 0, sizeof(pParse[0]));
30733078
return 1;
30743079
}
@@ -3225,6 +3230,7 @@ static JsonParse *jsonParseFuncArg(
32253230
int eType; /* Datatype of pArg */
32263231
JsonParse *p = 0; /* Value to be returned */
32273232
JsonParse *pFromCache = 0; /* Value taken from cache */
3233+
sqlite3 *db; /* The database connection */
32283234

32293235
assert( ctx!=0 );
32303236
eType = sqlite3_value_type(pArg);
@@ -3238,14 +3244,16 @@ static JsonParse *jsonParseFuncArg(
32383244
return pFromCache;
32393245
}
32403246
}
3247+
db = sqlite3_context_db_handle(ctx);
32413248
rebuild_from_cache:
3242-
p = sqlite3_malloc64( sizeof(*p) );
3249+
p = sqlite3DbMallocZero(db, sizeof(*p));
32433250
if( p==0 ) goto json_pfa_oom;
32443251
memset(p, 0, sizeof(*p));
3252+
p->db = db;
32453253
p->nJPRef = 1;
32463254
if( pFromCache!=0 ){
32473255
u32 nBlob = pFromCache->nBlob;
3248-
p->aBlob = sqlite3_malloc64( nBlob );
3256+
p->aBlob = sqlite3DbMallocRaw(db, nBlob);
32493257
if( p->aBlob==0 ) goto json_pfa_oom;
32503258
memcpy(p->aBlob, pFromCache->aBlob, nBlob);
32513259
p->nBlobAlloc = p->nBlob = nBlob;
@@ -3501,7 +3509,7 @@ static void jsonParseFunc(
35013509
if( p==0 ) return;
35023510
if( argc==1 ){
35033511
jsonDebugPrintBlob(p, 0, p->nBlob, 0, &out);
3504-
sqlite3_result_text64(ctx, out.zText, out.nChar, sqlite3_free, SQLITE_UTF8);
3512+
sqlite3_result_text64(ctx, out.zText, out.nChar, SQLITE_DYNAMIC, SQLITE_UTF8);
35053513
}else{
35063514
jsonShowParse(p);
35073515
}
@@ -4320,6 +4328,7 @@ static void jsonErrorFunc(
43204328
assert( argc==1 );
43214329
UNUSED_PARAMETER(argc);
43224330
memset(&s, 0, sizeof(s));
4331+
s.db = sqlite3_context_db_handle(ctx);
43234332
if( jsonFuncArgMightBeBinary(argv[0]) ){
43244333
s.aBlob = (u8*)sqlite3_value_blob(argv[0]);
43254334
s.nBlob = sqlite3_value_bytes(argv[0]);
@@ -4609,9 +4618,9 @@ static int jsonEachConnect(
46094618
"CREATE TABLE x(key,value,type,atom,id,parent,fullkey,path,"
46104619
"json HIDDEN,root HIDDEN)");
46114620
if( rc==SQLITE_OK ){
4612-
pNew = (JsonEachConnection*)(*ppVtab = sqlite3_malloc( sizeof(*pNew) ));
4621+
pNew = (JsonEachConnection*)sqlite3DbMallocZero(db, sizeof(*pNew));
4622+
*ppVtab = (sqlite3_vtab*)pNew;
46134623
if( pNew==0 ) return SQLITE_NOMEM;
4614-
memset(pNew, 0, sizeof(*pNew));
46154624
sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
46164625
pNew->db = db;
46174626
}
@@ -4620,7 +4629,8 @@ static int jsonEachConnect(
46204629

46214630
/* destructor for json_each virtual table */
46224631
static int jsonEachDisconnect(sqlite3_vtab *pVtab){
4623-
sqlite3_free(pVtab);
4632+
JsonEachConnection *p = (JsonEachConnection*)pVtab;
4633+
sqlite3DbFree(p->db, pVtab);
46244634
return SQLITE_OK;
46254635
}
46264636

@@ -4630,9 +4640,8 @@ static int jsonEachOpenEach(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
46304640
JsonEachCursor *pCur;
46314641

46324642
UNUSED_PARAMETER(p);
4633-
pCur = sqlite3_malloc( sizeof(*pCur) );
4643+
pCur = sqlite3DbMallocZero(pVtab->db, sizeof(*pCur));
46344644
if( pCur==0 ) return SQLITE_NOMEM;
4635-
memset(pCur, 0, sizeof(*pCur));
46364645
pCur->db = pVtab->db;
46374646
jsonStringZero(&pCur->path);
46384647
*ppCursor = &pCur->base;
@@ -4669,7 +4678,7 @@ static int jsonEachClose(sqlite3_vtab_cursor *cur){
46694678
JsonEachCursor *p = (JsonEachCursor*)cur;
46704679
jsonEachCursorReset(p);
46714680

4672-
sqlite3_free(cur);
4681+
sqlite3DbFree(p->db, cur);
46734682
return SQLITE_OK;
46744683
}
46754684

@@ -5003,6 +5012,7 @@ static int jsonEachFilter(
50035012
if( idxNum==0 ) return SQLITE_OK;
50045013
memset(&p->sParse, 0, sizeof(p->sParse));
50055014
p->sParse.nJPRef = 1;
5015+
p->sParse.db = p->db;
50065016
if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
50075017
if( jsonFuncArgMightBeBinary(argv[0]) ){
50085018
p->sParse.nBlob = sqlite3_value_bytes(argv[0]);

0 commit comments

Comments
 (0)