Fossil

Check-in [9b4f2d8e98]
Login

Check-in [9b4f2d8e98]

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

Overview
Comment:More TH1 performance optimizations: Go directly to malloc() rather than through the Th_Malloc() intermediary.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 9b4f2d8e98d86d12cf220bc8e2561c27be4466f71be80a7baf8fc956cb31d7c3
User & Date: drh 2021-01-27 13:32:29.160
Context
2021-01-27
14:14
Remove redundant length check from captcha processing. [forum:/forumpost/f406019983|Forum post f406019983]. ... (check-in: 43981c5d62 user: drh tags: trunk)
13:32
More TH1 performance optimizations: Go directly to malloc() rather than through the Th_Malloc() intermediary. ... (check-in: 9b4f2d8e98 user: drh tags: trunk)
12:38
Performance optimizations in the TH1 interpreter. ... (check-in: b26eea7ee0 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/main.c.
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
  ** FIXME: The next two lines cannot always be enabled; however, they
  **        are very useful for tracking down TH1 memory leaks.
  */
  if( fossil_getenv("TH1_DELETE_INTERP")!=0 ){
    if( g.interp ){
      Th_DeleteInterp(g.interp); g.interp = 0;
    }
    assert( Th_GetOutstandingMalloc()==0 );
  }
}

/*
** Convert all arguments from mbcs (or unicode) to UTF-8. Then
** search g.argv for arguments "--args FILENAME". If found, then
** (1) remove the two arguments from g.argv







<







383
384
385
386
387
388
389

390
391
392
393
394
395
396
  ** FIXME: The next two lines cannot always be enabled; however, they
  **        are very useful for tracking down TH1 memory leaks.
  */
  if( fossil_getenv("TH1_DELETE_INTERP")!=0 ){
    if( g.interp ){
      Th_DeleteInterp(g.interp); g.interp = 0;
    }

  }
}

/*
** Convert all arguments from mbcs (or unicode) to UTF-8. Then
** search g.argv for arguments "--args FILENAME". If found, then
** (1) remove the two arguments from g.argv
Changes to src/th.c.
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
*/
static void thBufferWriteResize(
  Th_Interp *interp,
  Buffer *pBuffer,
  const char *zAdd,
  int nAdd
){
  char *zNew;
  int nNew = (pBuffer->nBuf+nAdd)*2+32;
  zNew = (char *)Th_Malloc(interp, nNew);
  th_memcpy(zNew, pBuffer->zBuf, pBuffer->nBuf);
  Th_Free(interp, pBuffer->zBuf);
  pBuffer->nBufAlloc = nNew;
  pBuffer->zBuf = zNew;
  th_memcpy(&pBuffer->zBuf[pBuffer->nBuf], zAdd, nAdd);
  pBuffer->nBuf += nAdd;
}
static void thBufferWriteFast(
  Th_Interp *interp,
  Buffer *pBuffer,
  const char *zAdd,







<

<
<
|

<







219
220
221
222
223
224
225

226


227
228

229
230
231
232
233
234
235
*/
static void thBufferWriteResize(
  Th_Interp *interp,
  Buffer *pBuffer,
  const char *zAdd,
  int nAdd
){

  int nNew = (pBuffer->nBuf+nAdd)*2+32;


  pBuffer->zBuf = Th_Realloc(interp, pBuffer->zBuf, nNew);
  pBuffer->nBufAlloc = nNew;

  th_memcpy(&pBuffer->zBuf[pBuffer->nBuf], zAdd, nAdd);
  pBuffer->nBuf += nAdd;
}
static void thBufferWriteFast(
  Th_Interp *interp,
  Buffer *pBuffer,
  const char *zAdd,
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
    pInterp->nResult = 0;
    return zResult;
  }else{
    return (char *)Th_Malloc(pInterp, 1);
  }
}


/*
** Wrappers around the supplied malloc() and free()
*/
void *Th_Malloc(Th_Interp *pInterp, int nByte){
  void *p = pInterp->pVtab->xMalloc(nByte);
  if( p ){
    memset(p, 0, nByte);
  }
  return p;
}
void Th_Free(Th_Interp *pInterp, void *z){
  if( z ){
    pInterp->pVtab->xFree(z);
  }
}

/*
** Install a new th1 command.
**
** If a command of the same name already exists, it is deleted automatically.
*/
int Th_CreateCommand(
  Th_Interp *interp,







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1533
1534
1535
1536
1537
1538
1539

















1540
1541
1542
1543
1544
1545
1546
    pInterp->nResult = 0;
    return zResult;
  }else{
    return (char *)Th_Malloc(pInterp, 1);
  }
}


















/*
** Install a new th1 command.
**
** If a command of the same name already exists, it is deleted automatically.
*/
int Th_CreateCommand(
  Th_Interp *interp,
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
  /* Delete the interpreter structure itself. */
  Th_Free(interp, (void *)interp);
}

/*
** Create a new interpreter.
*/
Th_Interp * Th_CreateInterp(Th_Vtab *pVtab){
  Th_Interp *p;

  /* Allocate and initialise the interpreter and the global frame */
  p = pVtab->xMalloc(sizeof(Th_Interp) + sizeof(Th_Frame));
  memset(p, 0, sizeof(Th_Interp));
  p->pVtab = pVtab;
  p->paCmd = Th_HashNew(p);
  thPushFrame(p, (Th_Frame *)&p[1]);
  thInitialize(p);

  return p;
}








|



|

<







1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831

1832
1833
1834
1835
1836
1837
1838
  /* Delete the interpreter structure itself. */
  Th_Free(interp, (void *)interp);
}

/*
** Create a new interpreter.
*/
Th_Interp * Th_CreateInterp(void){
  Th_Interp *p;

  /* Allocate and initialise the interpreter and the global frame */
  p = Th_Malloc(0, sizeof(Th_Interp) + sizeof(Th_Frame));
  memset(p, 0, sizeof(Th_Interp));

  p->paCmd = Th_HashNew(p);
  thPushFrame(p, (Th_Frame *)&p[1]);
  thInitialize(p);

  return p;
}

Changes to src/th.h.
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
** Opaque handle for interpeter.
*/
typedef struct Th_Interp Th_Interp;

/*
** Create and delete interpreters.
*/
Th_Interp * Th_CreateInterp(Th_Vtab *pVtab);
void Th_DeleteInterp(Th_Interp *);

/*
** Evaluate an TH program in the stack frame identified by parameter
** iFrame, according to the following rules:
**
**   * If iFrame is 0, this means the current frame.







|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
** Opaque handle for interpeter.
*/
typedef struct Th_Interp Th_Interp;

/*
** Create and delete interpreters.
*/
Th_Interp * Th_CreateInterp(void);
void Th_DeleteInterp(Th_Interp *);

/*
** Evaluate an TH program in the stack frame identified by parameter
** iFrame, according to the following rules:
**
**   * If iFrame is 0, this means the current frame.
119
120
121
122
123
124
125



126

127
128
129
130
131
132
133
134
*/
int Th_ErrorMessage(Th_Interp *, const char *, const char *, int);

/*
** Access the memory management functions associated with the specified
** interpreter.
*/



void *Th_Malloc(Th_Interp *, int);

void Th_Free(Th_Interp *, void *);

/*
** Functions for handling TH lists.
*/
int Th_ListAppend(Th_Interp *, char **, int *, const char *, int);
int Th_SplitList(Th_Interp *, const char *, int, char ***, int **, int *);








>
>
>
|
>
|







119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
*/
int Th_ErrorMessage(Th_Interp *, const char *, const char *, int);

/*
** Access the memory management functions associated with the specified
** interpreter.
*/
void *fossil_malloc_zero(size_t);
void *fossil_realloc(void*,size_t);
void fossil_free(void*);
#define Th_Malloc(I,N)     fossil_malloc_zero(N)
#define Th_Realloc(I,P,N)  fossil_realloc(P,N)
#define Th_Free(I,P)       fossil_free(P)

/*
** Functions for handling TH lists.
*/
int Th_ListAppend(Th_Interp *, char **, int *, const char *, int);
int Th_SplitList(Th_Interp *, const char *, int, char ***, int **, int *);

Changes to src/th_main.c.
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/*
** These macros are used within this file to detect if the repository and
** configuration ("user") database are currently open.
*/
#define Th_IsRepositoryOpen()     (g.repositoryOpen)
#define Th_IsConfigOpen()         (g.zConfigDbName!=0)

/*
** Global variable counting the number of outstanding calls to malloc()
** made by the th1 implementation. This is used to catch memory leaks
** in the interpreter. Obviously, it also means th1 is not threadsafe.
*/
static int nOutstandingMalloc = 0;

/*
** Implementations of malloc() and free() to pass to the interpreter.
*/
static void *xMalloc(unsigned int n){
  void *p = fossil_malloc(n);
  if( p ){
    nOutstandingMalloc++;
  }
  return p;
}
static void xFree(void *p){
  if( p ){
    nOutstandingMalloc--;
  }
  free(p);
}
static Th_Vtab vtab = { xMalloc, xFree };

/*
** Returns the number of outstanding TH1 memory allocations.
*/
int Th_GetOutstandingMalloc(){
  return nOutstandingMalloc;
}

/*
** Generate a TH1 trace message if debugging is enabled.
*/
void Th_Trace(const char *zFormat, ...){
  va_list ap;
  va_start(ap, zFormat);







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







66
67
68
69
70
71
72































73
74
75
76
77
78
79
/*
** These macros are used within this file to detect if the repository and
** configuration ("user") database are currently open.
*/
#define Th_IsRepositoryOpen()     (g.repositoryOpen)
#define Th_IsConfigOpen()         (g.zConfigDbName!=0)

































/*
** Generate a TH1 trace message if debugging is enabled.
*/
void Th_Trace(const char *zFormat, ...){
  va_list ap;
  va_start(ap, zFormat);
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
    */
    Th_OpenConfig(!noRepo);
  }
  if( forceReset || forceTcl || g.interp==0 ){
    int created = 0;
    int i;
    if( g.interp==0 ){
      g.interp = Th_CreateInterp(&vtab);
      created = 1;
    }
    if( forceReset || created ){
      th_register_language(g.interp);     /* Basic scripting commands. */
    }
#ifdef FOSSIL_ENABLE_TCL
    if( forceTcl || fossil_getenv("TH1_ENABLE_TCL")!=0 ||







|







2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
    */
    Th_OpenConfig(!noRepo);
  }
  if( forceReset || forceTcl || g.interp==0 ){
    int created = 0;
    int i;
    if( g.interp==0 ){
      g.interp = Th_CreateInterp();
      created = 1;
    }
    if( forceReset || created ){
      th_register_language(g.interp);     /* Basic scripting commands. */
    }
#ifdef FOSSIL_ENABLE_TCL
    if( forceTcl || fossil_getenv("TH1_ENABLE_TCL")!=0 ||
Changes to src/util.c.
56
57
58
59
60
61
62






63
64
65
66
67
68
69
/*
** Malloc and free routines that cannot fail
*/
void *fossil_malloc(size_t n){
  void *p = malloc(n==0 ? 1 : n);
  if( p==0 ) fossil_panic("out of memory");
  return p;






}
void fossil_free(void *p){
  free(p);
}
void *fossil_realloc(void *p, size_t n){
  p = realloc(p, n);
  if( p==0 ) fossil_panic("out of memory");







>
>
>
>
>
>







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/*
** Malloc and free routines that cannot fail
*/
void *fossil_malloc(size_t n){
  void *p = malloc(n==0 ? 1 : n);
  if( p==0 ) fossil_panic("out of memory");
  return p;
}
void *fossil_malloc_zero(size_t n){
  void *p = malloc(n==0 ? 1 : n);
  if( p==0 ) fossil_panic("out of memory");
  memset(p, 0, n);
  return p;
}
void fossil_free(void *p){
  free(p);
}
void *fossil_realloc(void *p, size_t n){
  p = realloc(p, n);
  if( p==0 ) fossil_panic("out of memory");