/ Check-in [c93298d5]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Instrumentation and changes in an effort to reduce thread contention.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | reduced-thread-contention
Files: files | file ages | folders
SHA3-256: c93298d5ae11b55bc5df34f5f24abb6b58f1749bcd4b0766904cf53d6458cec6
User & Date: drh 2017-08-27 10:55:38
Context
2017-08-27
10:55
Instrumentation and changes in an effort to reduce thread contention. Leaf check-in: c93298d5 user: drh tags: reduced-thread-contention
2017-08-25
19:51
Fix a few over-length source code lines. No functional changes. check-in: 1783c54c user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/malloc.c.

306
307
308
309
310
311
312

313
314

315
316
317
318
319
320
321
322
323
324
325
326



327
328
329
330
331
332
333
...
355
356
357
358
359
360
361

362
363



364
365
366
367
368
369
370
...
397
398
399
400
401
402
403

404
405
406
407
408
409
410

/*
** Each thread may only have a single outstanding allocation from
** xScratchMalloc().  We verify this constraint in the single-threaded
** case by setting scratchAllocOut to 1 when an allocation
** is outstanding clearing it when the allocation is freed.
*/

#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
static int scratchAllocOut = 0;

#endif


/*
** Allocate memory that is to be used and released right away.
** This routine is similar to alloca() in that it is not intended
** for situations where the memory might be held long-term.  This
** routine is intended to get memory to old large transient data
** structures that would not normally fit on the stack of an
** embedded processor.
*/
void *sqlite3ScratchMalloc(int n){



  void *p;
  assert( n>0 );

  sqlite3_mutex_enter(mem0.mutex);
  sqlite3StatusHighwater(SQLITE_STATUS_SCRATCH_SIZE, n);
  if( mem0.nScratchFree && sqlite3GlobalConfig.szScratch>=n ){
    p = mem0.pScratchFree;
................................................................................
  ** This can only be checked in single-threaded mode.
  */
  assert( scratchAllocOut==0 );
  if( p ) scratchAllocOut++;
#endif

  return p;

}
void sqlite3ScratchFree(void *p){



  if( p ){

#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
    /* Verify that no more than two scratch allocation per thread
    ** is outstanding at one time.  (This is only checked in the
    ** single-threaded case since checking in the multi-threaded case
    ** would be much more complicated.) */
................................................................................
        sqlite3GlobalConfig.m.xFree(p);
        sqlite3_mutex_leave(mem0.mutex);
      }else{
        sqlite3GlobalConfig.m.xFree(p);
      }
    }
  }

}

/*
** TRUE if p is a lookaside memory allocation from db
*/
#ifndef SQLITE_OMIT_LOOKASIDE
static int isLookaside(sqlite3 *db, void *p){







>


>












>
>
>







 







>


>
>
>







 







>







306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
...
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
...
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420

/*
** Each thread may only have a single outstanding allocation from
** xScratchMalloc().  We verify this constraint in the single-threaded
** case by setting scratchAllocOut to 1 when an allocation
** is outstanding clearing it when the allocation is freed.
*/
#ifndef SQLITE_DISABLE_SCRATCH_MALLOC
#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
static int scratchAllocOut = 0;
#endif
#endif


/*
** Allocate memory that is to be used and released right away.
** This routine is similar to alloca() in that it is not intended
** for situations where the memory might be held long-term.  This
** routine is intended to get memory to old large transient data
** structures that would not normally fit on the stack of an
** embedded processor.
*/
void *sqlite3ScratchMalloc(int n){
#ifdef SQLITE_DISABLE_SCRATCH_MALLOC
  return sqlite3Malloc(n);
#else  
  void *p;
  assert( n>0 );

  sqlite3_mutex_enter(mem0.mutex);
  sqlite3StatusHighwater(SQLITE_STATUS_SCRATCH_SIZE, n);
  if( mem0.nScratchFree && sqlite3GlobalConfig.szScratch>=n ){
    p = mem0.pScratchFree;
................................................................................
  ** This can only be checked in single-threaded mode.
  */
  assert( scratchAllocOut==0 );
  if( p ) scratchAllocOut++;
#endif

  return p;
#endif /* SQLITE_DISABLE_SCRATCH_MALLOC */
}
void sqlite3ScratchFree(void *p){
#ifdef SQLITE_DISABLE_SCRATCH_MALLOC
  sqlite3_free(p);
#else
  if( p ){

#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
    /* Verify that no more than two scratch allocation per thread
    ** is outstanding at one time.  (This is only checked in the
    ** single-threaded case since checking in the multi-threaded case
    ** would be much more complicated.) */
................................................................................
        sqlite3GlobalConfig.m.xFree(p);
        sqlite3_mutex_leave(mem0.mutex);
      }else{
        sqlite3GlobalConfig.m.xFree(p);
      }
    }
  }
#endif /* SQLITE_DISABLE_SCRATCH_MALLOC */
}

/*
** TRUE if p is a lookaside memory allocation from db
*/
#ifndef SQLITE_OMIT_LOOKASIDE
static int isLookaside(sqlite3 *db, void *p){

Changes to src/mutex_unix.c.

38
39
40
41
42
43
44



45
46
47
48
49
50
51
...
217
218
219
220
221
222
223





224
225
226
227
228
229
230
...
265
266
267
268
269
270
271



272




273
274
275
276
277
278
279
/*
** Each recursive mutex is an instance of the following structure.
*/
struct sqlite3_mutex {
  pthread_mutex_t mutex;     /* Mutex controlling the lock */
#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR)
  int id;                    /* Mutex type */



#endif
#if SQLITE_MUTEX_NREF
  volatile int nRef;         /* Number of entrances */
  volatile pthread_t owner;  /* Thread that is within this mutex */
  int trace;                 /* True to trace changes */
#endif
};
................................................................................
static void pthreadMutexFree(sqlite3_mutex *p){
  assert( p->nRef==0 );
#if SQLITE_ENABLE_API_ARMOR
  if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE )
#endif
  {
    pthread_mutex_destroy(&p->mutex);





    sqlite3_free(p);
  }
#ifdef SQLITE_ENABLE_API_ARMOR
  else{
    (void)SQLITE_MISUSE_BKPT;
  }
#endif
................................................................................
      p->owner = self;
      p->nRef = 1;
    }
  }
#else
  /* Use the built-in recursive mutexes if they are available.
  */



  pthread_mutex_lock(&p->mutex);




#if SQLITE_MUTEX_NREF
  assert( p->nRef>0 || p->owner==0 );
  p->owner = pthread_self();
  p->nRef++;
#endif
#endif








>
>
>







 







>
>
>
>
>







 







>
>
>
|
>
>
>
>







38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
...
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
...
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
/*
** Each recursive mutex is an instance of the following structure.
*/
struct sqlite3_mutex {
  pthread_mutex_t mutex;     /* Mutex controlling the lock */
#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR)
  int id;                    /* Mutex type */
#endif
#ifdef SQLITE_COUNT_MUTEX_DELAYS
  u32 nCollide;
#endif
#if SQLITE_MUTEX_NREF
  volatile int nRef;         /* Number of entrances */
  volatile pthread_t owner;  /* Thread that is within this mutex */
  int trace;                 /* True to trace changes */
#endif
};
................................................................................
static void pthreadMutexFree(sqlite3_mutex *p){
  assert( p->nRef==0 );
#if SQLITE_ENABLE_API_ARMOR
  if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE )
#endif
  {
    pthread_mutex_destroy(&p->mutex);
#if SQLITE_COUNT_MUTEX_DELAYS
    if( p->nCollide ){
      printf("%d mutex delays for %p\n", p->nCollide, (void*)p);
    }
#endif
    sqlite3_free(p);
  }
#ifdef SQLITE_ENABLE_API_ARMOR
  else{
    (void)SQLITE_MISUSE_BKPT;
  }
#endif
................................................................................
      p->owner = self;
      p->nRef = 1;
    }
  }
#else
  /* Use the built-in recursive mutexes if they are available.
  */
#if SQLITE_COUNT_MUTEX_DELAYS
  if( pthread_mutex_trylock(&p->mutex) ){
    p->nCollide++;
    pthread_mutex_lock(&p->mutex);
  }
#else
  pthread_mutex_lock(&p->mutex);
#endif
#if SQLITE_MUTEX_NREF
  assert( p->nRef>0 || p->owner==0 );
  p->owner = pthread_self();
  p->nRef++;
#endif
#endif

Changes to src/pcache1.c.

247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
** to be serialized already.  There is no need for further mutexing.
*/
void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
  if( pcache1.isInit ){
    PgFreeslot *p;
    if( pBuf==0 ) sz = n = 0;
    sz = ROUNDDOWN8(sz);
    pcache1.szSlot = sz;
    pcache1.nSlot = pcache1.nFreeSlot = n;
    pcache1.nReserve = n>90 ? 10 : (n/10 + 1);
    pcache1.pStart = pBuf;
    pcache1.pFree = 0;
    pcache1.bUnderPressure = 0;
    while( n-- ){
      p = (PgFreeslot*)pBuf;







|







247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
** to be serialized already.  There is no need for further mutexing.
*/
void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
  if( pcache1.isInit ){
    PgFreeslot *p;
    if( pBuf==0 ) sz = n = 0;
    sz = ROUNDDOWN8(sz);
    pcache1.szSlot = n ? sz : 0;
    pcache1.nSlot = pcache1.nFreeSlot = n;
    pcache1.nReserve = n>90 ? 10 : (n/10 + 1);
    pcache1.pStart = pBuf;
    pcache1.pFree = 0;
    pcache1.bUnderPressure = 0;
    while( n-- ){
      p = (PgFreeslot*)pBuf;