From d859dc2b25c55ab10f70979f76470bdba9f53165 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 2 Apr 2022 14:30:58 +0000 Subject: [PATCH] In-line the sqlite3VdbeSerialPut() routine into the OP_MakeRecord opcode. This allows some duplicate comparisons to be omitted, resulting in a size reduction and performance increase. FossilOrigin-Name: 6f4d6f212a3558c27be6e9dcf71cec43c424d445e5889c6e91dde84a19c5a2c1 --- manifest | 16 +++++++------- manifest.uuid | 2 +- src/vdbe.c | 37 +++++++++++++++++++++++++++----- src/vdbeInt.h | 9 +++++++- src/vdbeaux.c | 59 ++++----------------------------------------------- 5 files changed, 53 insertions(+), 70 deletions(-) diff --git a/manifest b/manifest index 1aaae798d6..c5af0b4f6d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\sputVarint32()\smacro\sdoes\snot\soptimize\swell.\s\sSo\sexpand\sit\sinto\sin-line\ncode\sin\splaces\swere\sperformance\sis\san\sissue. -D 2022-04-01T21:01:37.702 +C In-line\sthe\ssqlite3VdbeSerialPut()\sroutine\sinto\sthe\sOP_MakeRecord\sopcode.\nThis\sallows\ssome\sduplicate\scomparisons\sto\sbe\somitted,\sresulting\sin\sa\ssize\nreduction\sand\sperformance\sincrease. +D 2022-04-02T14:30:58.141 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -624,11 +624,11 @@ F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 F src/util.c 602fe229f32a96ceccae4f40824129669582096f7c355f53dbac156c9fecef23 F src/vacuum.c 6c38ddc52f0619865c91dae9c441d4d48bf3040d7dc1bc5b22da1e45547ed0b3 -F src/vdbe.c ced0c7b4b872bd30b25f40be70c0ecae095b1dafd9510912ed24369b7efef335 +F src/vdbe.c 3500a7ebd2121765ce422b971bf65ab5f4d3d177b7ed2c04270423fb77f45b35 F src/vdbe.h a1d0e3b934e835e73edd146f2e7c4eadb711b5c9875c18159a57483fd78e550e -F src/vdbeInt.h 22babf1e585ae7e5c49f2e6442969b88f07bdcc3d154164346d25ef4efa3ebf3 +F src/vdbeInt.h 106930790a7619bc6e851be698e6e35c6b2b2e9e66c2f464d597d6b75b919679 F src/vdbeapi.c 5c498998c99667f16cac2519f2fa439fe46acf99a332b0caa73637fc2ab35c22 -F src/vdbeaux.c 7be57b47c60e348c32048d2e33c719b3d918a2aef36b30c6da571033c489dd58 +F src/vdbeaux.c 7a9df2e5700351221a152775e05d0b4ce9aa73b0d04bcfabeb85ab2229052bac F src/vdbeblob.c 5e61ce31aca17db8fb60395407457a8c1c7fb471dde405e0cd675974611dcfcd F src/vdbemem.c 062cd58c54f887dc2eeb865686251c17237f791f0e6394e9c6f7a6f3c1a7e206 F src/vdbesort.c 43756031ca7430f7aec3ef904824a7883c4ede783e51f280d99b9b65c0796e35 @@ -1945,8 +1945,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 47a61fbd63928021098fbe492283f1afda7c293b3b2706c001192ae4ff1b2cbe -R ade274038cb2118d099723f504530cb1 +P 390c239e53cf936a97b268dce8171f0b17050542ae64735ca8ef375fec2c9544 +R b3527f8e2f58b460cb9579ec710b98c3 U drh -Z 4ae04a2d928465896e499e8a40353d10 +Z dbc3ad7d55ca1ccbb3a168f87a1e7a5d # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 8c666935af..901d9eb8a8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -390c239e53cf936a97b268dce8171f0b17050542ae64735ca8ef375fec2c9544 \ No newline at end of file +6f4d6f212a3558c27be6e9dcf71cec43c424d445e5889c6e91dde84a19c5a2c1 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 07dfc63258..0c7447e8a8 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -3384,15 +3384,42 @@ case OP_MakeRecord: { while( 1 /*exit-by-break*/ ){ serial_type = pRec->uTemp; /* EVIDENCE-OF: R-06529-47362 Following the size varint are one or more - ** additional varints, one per column. */ - if( serial_type<0x80 ){ + ** additional varints, one per column. + ** EVIDENCE-OF: R-64536-51728 The values for each column in the record + ** immediately follow the header. */ + if( serial_type<=7 ){ *(zHdr++) = serial_type; + if( serial_type==0 ){ + /* NULL value. No change in zPayload */ + }else{ + u64 v; + u32 i, len; + if( serial_type==7 ){ + assert( sizeof(v)==sizeof(pRec->u.r) ); + memcpy(&v, &pRec->u.r, sizeof(v)); + swapMixedEndianFloat(v); + }else{ + v = pRec->u.i; + } + len = i = sqlite3SmallTypeSizes[serial_type]; + assert( i>0 ); + do{ + zPayload[--i] = (u8)(v&0xFF); + v >>= 8; + }while( i ); + zPayload += len; + } + }else if( serial_type<0x80 ){ + *(zHdr++) = serial_type; + if( serial_type>=14 ){ + memcpy(zPayload, pRec->z, pRec->n); + zPayload += pRec->n; + } }else{ zHdr += sqlite3PutVarint(zHdr, serial_type); + memcpy(zPayload, pRec->z, pRec->n); + zPayload += pRec->n; } - /* EVIDENCE-OF: R-64536-51728 The values for each column in the record - ** immediately follow the header. */ - zPayload += sqlite3VdbeSerialPut(zPayload, pRec, serial_type); /* content */ if( pRec==pLast ) break; pRec++; } diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 792ead7b5f..968500b322 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -532,6 +532,8 @@ struct ValueList { sqlite3_value *pOut; /* Register to hold each decoded output value */ }; +const u8 sqlite3SmallTypeSizes[128]; + /* ** Function prototypes */ @@ -544,7 +546,12 @@ int SQLITE_NOINLINE sqlite3VdbeFinishMoveto(VdbeCursor*); int sqlite3VdbeCursorRestore(VdbeCursor*); u32 sqlite3VdbeSerialTypeLen(u32); u8 sqlite3VdbeOneByteSerialTypeLen(u8); -u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32); +#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT + u64 sqlite3FloatSwap(u64 in); +# define swapMixedEndianFloat(X) X = sqlite3FloatSwap(X) +#else +# define swapMixedEndianFloat(X) +#endif void sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); void sqlite3VdbeDeleteAuxData(sqlite3*, AuxData**, int, int); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index ecdd50f700..aa45cae54c 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3557,7 +3557,7 @@ int sqlite3VdbeCursorRestore(VdbeCursor *p){ ** sqlite3VdbeSerialType() ** sqlite3VdbeSerialTypeLen() ** sqlite3VdbeSerialLen() -** sqlite3VdbeSerialPut() +** sqlite3VdbeSerialPut() <--- in-lined into OP_MakeRecord as of 2022-04-02 ** sqlite3VdbeSerialGet() ** ** encapsulate the code that serializes values for storage in SQLite @@ -3669,7 +3669,7 @@ u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){ /* ** The sizes for serial types less than 128 */ -static const u8 sqlite3SmallTypeSizes[] = { +const u8 sqlite3SmallTypeSizes[128] = { /* 0 1 2 3 4 5 6 7 8 9 */ /* 0 */ 0, 1, 2, 3, 4, 6, 8, 8, 0, 0, /* 10 */ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, @@ -3738,7 +3738,7 @@ u8 sqlite3VdbeOneByteSerialTypeLen(u8 serial_type){ ** so we trust him. */ #ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT -static u64 floatSwap(u64 in){ +u64 sqlite3FloatSwap(u64 in){ union { u64 r; u32 i[2]; @@ -3751,59 +3751,8 @@ static u64 floatSwap(u64 in){ u.i[1] = t; return u.r; } -# define swapMixedEndianFloat(X) X = floatSwap(X) -#else -# define swapMixedEndianFloat(X) -#endif +#endif /* SQLITE_MIXED_ENDIAN_64BIT_FLOAT */ -/* -** Write the serialized data blob for the value stored in pMem into -** buf. It is assumed that the caller has allocated sufficient space. -** Return the number of bytes written. -** -** nBuf is the amount of space left in buf[]. The caller is responsible -** for allocating enough space to buf[] to hold the entire field, exclusive -** of the pMem->u.nZero bytes for a MEM_Zero value. -** -** Return the number of bytes actually written into buf[]. The number -** of bytes in the zero-filled tail is included in the return value only -** if those bytes were zeroed in buf[]. -*/ -u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){ - u32 len; - - /* Integer and Real */ - if( serial_type<=7 && serial_type>0 ){ - u64 v; - u32 i; - if( serial_type==7 ){ - assert( sizeof(v)==sizeof(pMem->u.r) ); - memcpy(&v, &pMem->u.r, sizeof(v)); - swapMixedEndianFloat(v); - }else{ - v = pMem->u.i; - } - len = i = sqlite3SmallTypeSizes[serial_type]; - assert( i>0 ); - do{ - buf[--i] = (u8)(v&0xFF); - v >>= 8; - }while( i ); - return len; - } - - /* String or blob */ - if( serial_type>=12 ){ - assert( pMem->n + ((pMem->flags & MEM_Zero)?pMem->u.nZero:0) - == (int)sqlite3VdbeSerialTypeLen(serial_type) ); - len = pMem->n; - if( len>0 ) memcpy(buf, pMem->z, len); - return len; - } - - /* NULL or constants 0 or 1 */ - return 0; -} /* Input "x" is a sequence of unsigned characters that represent a ** big-endian integer. Return the equivalent native integer