MINOR: chunk: inline alloc_trash_chunk()

This function is responsible for all calls to pool_alloc(trash), whose
total size can be huge. As such it's quite a pain that it doesn't provide
more hints about its users. However, since the function is tiny, it fully
makes sense to inline it, the code is less than 0.1% larger with this.
This way we can now detect where the callers are via "show profiling",
e.g.:

       0 1953671           0 32071463136| 0x59960f main+0x10676f p_free(-16416) [pool=trash]
       0       1           0       16416| 0x59960f main+0x10676f p_free(-16416) [pool=trash]
 1953672       0 32071479552           0| 0x599561 main+0x1066c1 p_alloc(16416) [pool=trash]
       0  976835           0 16035723360| 0x576ca7 http_reply_to_htx+0x447/0x920 p_free(-16416) [pool=trash]
       0       1           0       16416| 0x576ca7 http_reply_to_htx+0x447/0x920 p_free(-16416) [pool=trash]
  976835       0 16035723360           0| 0x576a5d http_reply_to_htx+0x1fd/0x920 p_alloc(16416) [pool=trash]
       1       0       16416           0| 0x576a5d http_reply_to_htx+0x1fd/0x920 p_alloc(16416) [pool=trash]
This commit is contained in:
Willy Tarreau 2022-08-17 10:45:22 +02:00
parent 42b180dcdb
commit cc1a2a1867
2 changed files with 28 additions and 30 deletions

View File

@ -46,18 +46,8 @@ int chunk_asciiencode(struct buffer *dst, struct buffer *src, char qc);
int chunk_strcmp(const struct buffer *chk, const char *str);
int chunk_strcasecmp(const struct buffer *chk, const char *str);
struct buffer *get_trash_chunk(void);
struct buffer *alloc_trash_chunk(void);
int init_trash_buffers(int first);
/*
* free a trash chunk allocated by alloc_trash_chunk(). NOP on NULL.
*/
static inline void free_trash_chunk(struct buffer *chunk)
{
pool_free(pool_head_trash, chunk);
}
static inline void chunk_reset(struct buffer *chk)
{
chk->data = 0;
@ -96,6 +86,34 @@ static inline void chunk_initstr(struct buffer *chk, const char *str)
chk->size = 0; /* mark it read-only */
}
/*
* Allocate a trash chunk from the reentrant pool. The buffer starts at the
* end of the chunk. This chunk must be freed using free_trash_chunk(). This
* call may fail and the caller is responsible for checking that the returned
* pointer is not NULL.
*/
static forceinline struct buffer *alloc_trash_chunk(void)
{
struct buffer *chunk;
chunk = pool_alloc(pool_head_trash);
if (chunk) {
char *buf = (char *)chunk + sizeof(struct buffer);
*buf = 0;
chunk_init(chunk, buf,
pool_head_trash->size - sizeof(struct buffer));
}
return chunk;
}
/*
* free a trash chunk allocated by alloc_trash_chunk(). NOP on NULL.
*/
static forceinline void free_trash_chunk(struct buffer *chunk)
{
pool_free(pool_head_trash, chunk);
}
/* copies chunk <src> into <chk>. Returns 0 in case of failure. */
static inline int chunk_cpy(struct buffer *chk, const struct buffer *src)
{

View File

@ -98,26 +98,6 @@ int init_trash_buffers(int first)
return 1;
}
/*
* Allocate a trash chunk from the reentrant pool. The buffer starts at the
* end of the chunk. This chunk must be freed using free_trash_chunk(). This
* call may fail and the caller is responsible for checking that the returned
* pointer is not NULL.
*/
struct buffer *alloc_trash_chunk(void)
{
struct buffer *chunk;
chunk = pool_alloc(pool_head_trash);
if (chunk) {
char *buf = (char *)chunk + sizeof(struct buffer);
*buf = 0;
chunk_init(chunk, buf,
pool_head_trash->size - sizeof(struct buffer));
}
return chunk;
}
/*
* Does an snprintf() at the beginning of chunk <chk>, respecting the limit of
* at most chk->size chars. If the chk->len is over, nothing is added. Returns