Sat Oct  1 01:21:57 2005  Soeren Sandmann  <sandmann@redhat.com>

        * TODO: Update
This commit is contained in:
Soeren Sandmann
2005-10-01 05:21:25 +00:00
committed by Søren Sandmann Pedersen
parent 1b21157a12
commit cc1055d105
8 changed files with 99 additions and 130 deletions

View File

@ -1,3 +1,7 @@
Sat Oct 1 01:21:57 2005 Soeren Sandmann <sandmann@redhat.com>
* TODO: Update
Wed Sep 28 12:08:32 2005 Søren Sandmann <sandmann@redhat.com>
* sysprof-text.c: Add my name to the copyright statement

View File

@ -15,6 +15,8 @@ sysprof_SOURCES = \
sfile.c \
stackstash.h \
stackstash.c \
helper.c \
helper.h \
module/sysprof-module.h \
sysprof.c \
treeviewutils.h \
@ -33,6 +35,8 @@ sysprof_text_SOURCES = \
sfile.c \
stackstash.h \
stackstash.c \
helper.c \
helper.h \
module/sysprof-module.h \
signal-handler.h \
signal-handler.c \

97
TODO
View File

@ -1,35 +1,8 @@
Before 1.0:
- Update version numbers in source
- Make tarball
- Check that tarball works
- cvs commit
- cvs tag sysprof-1-0
- Update website
- Announce on Freshmeat
- Announce on gnome-announce
- Announce on kernel list.
- Announce on Gnomefiles
- Announce on news.gnome.org
- Send to slashdot/developers
- Announce on devtools list (?)
- Announce on Advogato
link to archive
Before 1.0.1:
* See if we can reproduce the problem where libraries didn't get correctly
reloaded after new versions were installed.
This is just the (deleted) problem.
* Build system
- Find out what distributions it actually works on
@ -43,10 +16,6 @@ Before 1.0.1:
Before 1.2:
* The handling of the global variable in signal-handler.[ch] needs to be
atomic - right now it isn't. The issue is what happens if a handled signal
arrives while we are manipulating the list?
* Figure out how to make sfile.[ch] use less memory.
- In general clean sfile.[ch] up a little:
- split out dfa in its own generic class
@ -205,23 +174,35 @@ http://www.linuxbase.org/spec/booksets/LSB-Embedded/LSB-Embedded/ehframe.html
- Reorganise stackstash and profile
- stackstash should just take traces of addresses without knowing
anything about what those addresses mean
anything about what those addresses mean.
- stacktraces should then begin with a process
- stackstash should be extended so that the "create_descendant"
and "create_ancestor" code in profile.c can use it directly.
At that point, get rid of the profile tree, and rename
profile.c to analyze.c.
- the profile tree will then just be a stackstash where the
addresses are presentation strings instead.
- Doing a profile will then amount to converting the raw stash
to one where the addresses have been looked up and converted to
presentation strings.
-=-=
- profile should take traces of pointers to presentation
objects without knowing anything about these presentation
objects.
- Creating a profile is then
- For each stack node, compute a presentation object
(probably need to export opaque stacknode objects
with set/get_user_data)
- For each stack node, compute a presentation object
(probably need to export opaque stacknode objects
with set/get_user_data)
- Send each stack trace to the profile module, along with
presentation objects. Maybe just a map from stack nodes
to presentation objects.
- Send each stack trace to the profile module, along with
presentation objects. Maybe just a map from stack nodes
to presentation objects.
- Charge 'self' properly to processes that don't get any stack trace at all
(probably we get that for free with stackstash reorganisation)
@ -446,8 +427,42 @@ Later:
The disk timeline should probably vary in intensity with the number of outstanding
disk requests.
DONE:
Before 1.0:
- Update version numbers in source
- Make tarball
- Check that tarball works
- cvs commit
- cvs tag sysprof-1-0
- Update website
- Announce on Freshmeat
- Announce on gnome-announce
- Announce on kernel list.
- Announce on Gnomefiles
- Announce on news.gnome.org
- Send to slashdot/developers
- Announce on devtools list (?)
- Announce on Advogato
link to archive
* The handling of the global variable in signal-handler.[ch] needs to be
atomic - right now it isn't. The issue is what happens if a handled signal
arrives while we are manipulating the list?
* (User space stack must probably be done in a thread - kernel
stack must probably be taken in the interrupt itself?
- Why this difference? The page tables should still be loaded. Is it

View File

@ -349,10 +349,12 @@ struct Info
};
static void
generate_object_table (Process *process, GSList *trace, gint size, gpointer data)
generate_object_table (GSList *trace, gint size, gpointer data)
{
Info *info = data;
GSList *list;
Process *process = trace->data;
trace = trace->next;
ensure_profile_object (info->profile_objects, process, 0);
@ -444,12 +446,14 @@ dump_trace (GSList *trace)
#endif
static void
generate_call_tree (Process *process, GSList *trace, gint size, gpointer data)
generate_call_tree (GSList *trace, gint size, gpointer data)
{
Info *info = data;
Node *match = NULL;
ProfileObject *proc = lookup_profile_object (info->profile_objects, process, 0);
GHashTable *seen_objects;
Process *process = trace->data;
trace = trace->next;
ProfileObject *proc = lookup_profile_object (info->profile_objects, process, 0);
for (match = info->profile->call_tree; match; match = match->siblings)
{

View File

@ -27,14 +27,12 @@ struct StackNode
gpointer address;
StackNode * siblings;
StackNode * children;
StackNode * next; /* next leaf with the same pid */
int size;
};
struct StackStash
{
StackNode *root;
GHashTable *leaves_by_process;
};
static StackNode *
@ -45,7 +43,6 @@ stack_node_new (void)
node->children = NULL;
node->address = NULL;
node->parent = NULL;
node->next = NULL;
node->size = 0;
return node;
}
@ -68,8 +65,6 @@ stack_stash_new (void)
{
StackStash *stash = g_new (StackStash, 1);
stash->leaves_by_process =
g_hash_table_new (g_direct_hash, g_direct_equal);
stash->root = NULL;
return stash;
}
@ -77,32 +72,18 @@ stack_stash_new (void)
static StackNode *
stack_node_add_trace (StackNode *node,
GList *bottom,
gint size,
StackNode **leaf)
gint size)
{
StackNode *match;
StackNode *n;
if (!bottom)
{
*leaf = NULL;
return node;
}
if (!bottom->next)
for (match = node; match != NULL; match = match->siblings)
{
/* A leaf must always be separate, so pids can
* point to them
*/
match = NULL;
}
else
{
for (match = node; match != NULL; match = match->siblings)
{
if (match->address == bottom->data)
break;
}
if (match->address == bottom->data)
break;
}
if (!match)
@ -114,71 +95,57 @@ stack_node_add_trace (StackNode *node,
}
match->children =
stack_node_add_trace (match->children, bottom->next, size, leaf);
stack_node_add_trace (match->children, bottom->next, size);
for (n = match->children; n; n = n->siblings)
n->parent = match;
if (!bottom->next)
{
match->size += size;
*leaf = match;
}
return node;
}
void
stack_stash_add_trace (StackStash *stash,
Process *process,
gulong *addrs,
int n_addrs,
int size)
{
GList *trace;
StackNode *leaf;
int i;
trace = NULL;
for (i = 0; i < n_addrs; ++i)
trace = g_list_prepend (trace, GINT_TO_POINTER (addrs[i]));
stash->root = stack_node_add_trace (stash->root, trace, size, &leaf);
leaf->next = g_hash_table_lookup (
stash->leaves_by_process, process);
g_hash_table_insert (
stash->leaves_by_process, process, leaf);
stash->root = stack_node_add_trace (stash->root, trace, size);
g_list_free (trace);
}
typedef struct CallbackInfo
{
StackFunction func;
gpointer data;
} CallbackInfo;
static void
do_callback (gpointer key, gpointer value, gpointer data)
do_callback (StackNode *node,
StackFunction stack_func,
gpointer data)
{
CallbackInfo *info = data;
Process *process = key;
StackNode *n;
StackNode *leaf = value;
while (leaf)
{
GSList *trace;
if (!node)
return;
trace = NULL;
for (n = leaf; n; n = n->parent)
do_callback (node->siblings, stack_func, data);
do_callback (node->children, stack_func, data);
if (!node->children)
{
StackNode *n;
GSList *trace = NULL;
for (n = node; n != NULL; n = n->parent)
trace = g_slist_prepend (trace, n->address);
info->func (process, trace, leaf->size, info->data);
stack_func (trace, node->size, data);
g_slist_free (trace);
leaf = leaf->next;
}
}
@ -187,11 +154,7 @@ stack_stash_foreach (StackStash *stash,
StackFunction stack_func,
gpointer data)
{
CallbackInfo info;
info.func = stack_func;
info.data = data;
g_hash_table_foreach (stash->leaves_by_process, do_callback, &info);
do_callback (stash->root, stack_func, data);
}
static void
@ -210,6 +173,5 @@ void
stack_stash_free (StackStash *stash)
{
stack_node_free (stash->root);
g_hash_table_destroy (stash->leaves_by_process);
g_free (stash);
}

View File

@ -25,15 +25,13 @@
typedef struct StackStash StackStash;
typedef void (* StackFunction) (Process *process,
GSList *trace,
typedef void (* StackFunction) (GSList *trace,
gint size,
gpointer data);
/* Stach */
StackStash *stack_stash_new (void);
void stack_stash_add_trace (StackStash *stash,
Process *process,
gulong *addrs,
gint n_addrs,
int size);

View File

@ -57,10 +57,8 @@ read_trace (StackStash *stash,
process_ensure_map (process, trace->pid,
(gulong)trace->addresses[i]);
}
stack_stash_add_trace (
stash, process,
(gulong *)trace->addresses, trace->n_addresses, 1);
add_trace_to_stash (&trace, stash);
}
void

View File

@ -266,7 +266,7 @@ time_diff (const GTimeVal *first,
return first_ms - second_ms;
}
#define RESET_DEAD_PERIOD 25
#define RESET_DEAD_PERIOD 5
static void
on_read (gpointer data)
@ -302,24 +302,8 @@ on_read (gpointer data)
if (rd > 0 && !app->generating_profile)
{
Process *process = process_get_from_pid (trace.pid);
int i;
/* char *filename = NULL; */
/* if (*trace.filename) */
/* filename = trace.filename; */
for (i = 0; i < trace.n_addresses; ++i)
{
process_ensure_map (process, trace.pid,
(gulong)trace.addresses[i]);
}
g_assert (!app->generating_profile);
stack_stash_add_trace (
app->stash, process,
(gulong *)trace.addresses, trace.n_addresses, 1);
add_trace_to_stash (&trace, app->stash);
app->n_samples++;
}