1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

Backport:

B-g#24795: SHOW PROFILE implementation

Don't use memory roots to store profiling information, because
memory roots make freeing the data a no-op, and thus long-running
processes with profiling turned on the whole time could eventually 
use all available memory.

Instead, use regular heap allocation and deallocation calls to 
manage profiling data.  Replace the leaky List usage with a similar-
behaving structure named "Queue".
This commit is contained in:
cmiller@zippy.cornsilk.net
2007-04-03 17:59:52 -04:00
parent 0b3dfea79a
commit 9816842b58
2 changed files with 147 additions and 75 deletions

View File

@ -83,6 +83,112 @@ class QUERY_PROFILE;
class PROFILING;
/**
Implements a persistent FIFO using server List method names. Not
thread-safe. Intended to be used on thread-local data only.
*/
template <class T> class Queue
{
private:
struct queue_item
{
T *payload;
struct queue_item *next, *previous;
};
struct queue_item *first, *last;
public:
Queue()
{
elements= 0;
first= last= NULL;
}
void empty()
{
struct queue_item *i, *after_i;
for (i= first; i != NULL; i= after_i)
{
after_i= i->next;
my_free((char *) i, MYF(0));
}
elements= 0;
}
ulong elements; /* The count of items in the Queue */
void push_back(T *payload)
{
struct queue_item *new_item;
new_item= (struct queue_item *) my_malloc(sizeof(struct queue_item), MYF(0));
new_item->payload= payload;
if (first == NULL)
first= new_item;
if (last != NULL)
{
DBUG_ASSERT(last->next == NULL);
last->next= new_item;
}
new_item->previous= last;
new_item->next= NULL;
last= new_item;
elements++;
}
T *pop()
{
struct queue_item *old_item= first;
T *ret= NULL;
if (first == NULL)
{
DBUG_PRINT("warning", ("tried to pop nonexistent item from Queue"));
return NULL;
}
ret= old_item->payload;
if (first->next != NULL)
first->next->previous= NULL;
else
last= NULL;
first= first->next;
my_free((char *)old_item, MYF(0));
elements--;
return ret;
}
bool is_empty()
{
DBUG_ASSERT(((elements > 0) && (first != NULL)) || ((elements == 0) || (first == NULL)));
return (elements == 0);
}
void *new_iterator()
{
return first;
}
void *iterator_next(void *current)
{
return ((struct queue_item *) current)->next;
}
T *iterator_value(void *current)
{
return ((struct queue_item *) current)->payload;
}
};
/**
A single entry in a single profile.
*/
@ -135,7 +241,7 @@ private:
char *query_source;
PROFILE_ENTRY profile_start;
PROFILE_ENTRY *profile_end;
List<PROFILE_ENTRY> entries;
Queue<PROFILE_ENTRY> entries;
QUERY_PROFILE(PROFILING *profiling_arg, char *query_source_arg, uint query_length_arg);
@ -169,13 +275,12 @@ private:
Not the system query_id, but a counter unique to profiling.
*/
query_id_t profile_id_counter;
MEM_ROOT mem_root;
THD *thd;
bool keeping;
QUERY_PROFILE *current;
QUERY_PROFILE *last;
List<QUERY_PROFILE> history;
Queue<QUERY_PROFILE> history;
query_id_t next_profile_id() { return(profile_id_counter++); }