From 2454e4a901c7221603cc43e41a47e5becb8b2309 Mon Sep 17 00:00:00 2001
From: drh <>
Date: Sat, 15 May 2021 19:36:36 +0000
Subject: [PATCH] Performance optimization in the memory allocation of
 allocateCursor.

FossilOrigin-Name: 9d16323d14370b737399eb52b69b70cc614f78fb8a1e93f21a348c34a30dd456
---
 manifest      | 14 +++++++-------
 manifest.uuid |  2 +-
 src/vdbe.c    | 40 +++++++++++++++++++++++++++++-----------
 src/vdbemem.c |  8 ++++++--
 4 files changed, 43 insertions(+), 21 deletions(-)

diff --git a/manifest b/manifest
index 987b4ee604..9686536309 100644
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Performance\soptimization\sto\sthe\sclearCell()\sroutine\sinside\sof\sbtree.
-D 2021-05-15T13:08:44.420
+C Performance\soptimization\sin\sthe\smemory\sallocation\sof\sallocateCursor.
+D 2021-05-15T19:36:36.998
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -615,13 +615,13 @@ F src/upsert.c df8f1727d62b5987c4fd302cd4d7c0c84ae57cd65683c5a34a740dfe24039235
 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
 F src/util.c 41c7a72da1df47864faa378a1c720b38adb288c6838cb6be5594511b6287a048
 F src/vacuum.c 492422c1463c076473bae1858799c7a0a5fe87a133d1223239447c422cd26286
-F src/vdbe.c b51cd7b4150d299efc396d7522b81616050bd0c0c61ef1238f8b94493fa12adf
+F src/vdbe.c b26c70a380b0dbaa121ab91245d8a6369b6777ccfd92145bfaa6a15b15fd93b7
 F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe
 F src/vdbeInt.h 58980223a32495ad059d10581b83e133abdc77248b1bab85c080cab8a13bd819
 F src/vdbeapi.c d9e99daf59fec928986838b3389a7337e82fec6b3b5de30206cb99fb4661b94e
 F src/vdbeaux.c 065a10392378109f08435bd50d03dff315e384cde2831d6b8dbaec05f33b10af
 F src/vdbeblob.c c6b8db50b227f66fb404215732068df76485b5b433e5f9d4d9ac27410b218193
-F src/vdbemem.c 947f2a65910edb4014dc981d33e414a68c51f169f9df8c4c493a0ba840b6eb1f
+F src/vdbemem.c 175c73ced03edbb0f6567a41c8032afaeb83372090fa7bddfc88a67e28da2b8a
 F src/vdbesort.c f5b5e473a7cee44e47a94817b042fd7172cf3aa2c0a7928a8339d612bcfdec5a
 F src/vdbetrace.c 666c6fd9f1b62be6999e072a45b913e3c2c3518bc60dfd4d54fe304130acb724
 F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c
@@ -1913,7 +1913,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 4ae64484c57740333322cebd713b50b01a5a5838d41c65f67e26d65769770789
-R c57f4aed344bc5813fc7501f2d476ff9
+P c4e02619a4dc8b07f658e7c88011991a086eb1e760d920b9024a11437daaabfd
+R 4816762a1807c6d973c9502508606581
 U drh
-Z d7b4c1d6b383cbf19bb45bb69313de60
+Z c8321cc153d7e5ab49215db310f82cea
diff --git a/manifest.uuid b/manifest.uuid
index df8f45d4c1..02adfeaf0e 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-c4e02619a4dc8b07f658e7c88011991a086eb1e760d920b9024a11437daaabfd
\ No newline at end of file
+9d16323d14370b737399eb52b69b70cc614f78fb8a1e93f21a348c34a30dd456
\ No newline at end of file
diff --git a/src/vdbe.c b/src/vdbe.c
index 26bb542d28..0a8aa3b673 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -275,18 +275,36 @@ static VdbeCursor *allocateCursor(
     sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
     p->apCsr[iCur] = 0;
   }
-  if( SQLITE_OK==sqlite3VdbeMemClearAndResize(pMem, nByte) ){
-    p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z;
-    memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
-    pCx->eCurType = eCurType;
-    pCx->iDb = iDb;
-    pCx->nField = nField;
-    pCx->aOffset = &pCx->aType[nField];
-    if( eCurType==CURTYPE_BTREE ){
-      pCx->uc.pCursor = (BtCursor*)
-          &pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
-      sqlite3BtreeCursorZero(pCx->uc.pCursor);
+
+  /* There used to be a call to sqlite3VdbeMemClearAndResize() to make sure
+  ** the pMem used to hold space for the cursor has enough storage available
+  ** in pMem->zMalloc.  But for the special case of the aMem[] entries used
+  ** to hold cursors, it is faster to in-line the logic. */
+  assert( pMem->flags==MEM_Undefined );
+  assert( (pMem->flags & MEM_Dyn)==0 );
+  assert( pMem->szMalloc==0 || pMem->z==pMem->zMalloc );
+  if( pMem->szMalloc<nByte ){
+    if( pMem->szMalloc>0 ){
+      sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
     }
+    pMem->z = pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, nByte);
+    if( pMem->zMalloc==0 ){
+      pMem->szMalloc = 0;
+      return 0;
+    }
+    pMem->szMalloc = nByte;
+  }
+
+  p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->zMalloc;
+  memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
+  pCx->eCurType = eCurType;
+  pCx->iDb = iDb;
+  pCx->nField = nField;
+  pCx->aOffset = &pCx->aType[nField];
+  if( eCurType==CURTYPE_BTREE ){
+    pCx->uc.pCursor = (BtCursor*)
+        &pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
+    sqlite3BtreeCursorZero(pCx->uc.pCursor);
   }
   return pCx;
 }
diff --git a/src/vdbemem.c b/src/vdbemem.c
index 384eacc015..fd5212c8a9 100644
--- a/src/vdbemem.c
+++ b/src/vdbemem.c
@@ -75,7 +75,9 @@ int sqlite3VdbeCheckMemInvariants(Mem *p){
 
   /* The szMalloc field holds the correct memory allocation size */
   assert( p->szMalloc==0
-       || p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc) );
+       || (p->flags==MEM_Undefined 
+           && p->szMalloc<=sqlite3DbMallocSize(p->db,p->zMalloc))
+       || p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc));
 
   /* If p holds a string or blob, the Mem.z must point to exactly
   ** one of the following:
@@ -239,7 +241,9 @@ SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
   testcase( bPreserve && pMem->z==0 );
 
   assert( pMem->szMalloc==0
-       || pMem->szMalloc==sqlite3DbMallocSize(pMem->db, pMem->zMalloc) );
+       || (pMem->flags==MEM_Undefined 
+           && pMem->szMalloc<=sqlite3DbMallocSize(pMem->db,pMem->zMalloc))
+       || pMem->szMalloc==sqlite3DbMallocSize(pMem->db,pMem->zMalloc));
   if( pMem->szMalloc>0 && bPreserve && pMem->z==pMem->zMalloc ){
     if( pMem->db ){
       pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);