mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2026-02-12 16:10:54 +00:00
libsysprof-analyze: pre-sort frames during loading
That way we can be sure that we only have to look forward to find closing pairs of operation (such as allocation/free, or appended capture data from controlfd ring buffers).
This commit is contained in:
@ -774,6 +774,80 @@ load_progress (Load *load,
|
|||||||
load->progress (fraction, message, load->progress_data);
|
load->progress (fraction, message, load->progress_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
sort_by_time (gconstpointer a,
|
||||||
|
gconstpointer b,
|
||||||
|
gpointer base)
|
||||||
|
{
|
||||||
|
const SysprofDocumentFramePointer *aptr = a;
|
||||||
|
const SysprofDocumentFramePointer *bptr = b;
|
||||||
|
const SysprofCaptureFrame *aframe = (const SysprofCaptureFrame *)((const guint8 *)base + aptr->offset);
|
||||||
|
const SysprofCaptureFrame *bframe = (const SysprofCaptureFrame *)((const guint8 *)base + bptr->offset);
|
||||||
|
|
||||||
|
if (aframe->time < bframe->time)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (aframe->time > bframe->time)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (aframe->type == SYSPROF_CAPTURE_FRAME_MARK && bframe->type == SYSPROF_CAPTURE_FRAME_MARK)
|
||||||
|
{
|
||||||
|
const SysprofCaptureMark *amark = (const SysprofCaptureMark *)aframe;
|
||||||
|
const SysprofCaptureMark *bmark = (const SysprofCaptureMark *)bframe;
|
||||||
|
|
||||||
|
if (amark->duration > bmark->duration)
|
||||||
|
return -1;
|
||||||
|
else if (amark->duration < bmark->duration)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
sort_by_time_swapped (gconstpointer a,
|
||||||
|
gconstpointer b,
|
||||||
|
gpointer base)
|
||||||
|
{
|
||||||
|
const SysprofDocumentFramePointer *aptr = a;
|
||||||
|
const SysprofDocumentFramePointer *bptr = b;
|
||||||
|
const SysprofCaptureFrame *aframe = (const SysprofCaptureFrame *)((const guint8 *)base + aptr->offset);
|
||||||
|
const SysprofCaptureFrame *bframe = (const SysprofCaptureFrame *)((const guint8 *)base + bptr->offset);
|
||||||
|
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||||
|
gint64 atime = GINT64_FROM_BE (aframe->time);
|
||||||
|
gint64 btime = GINT64_FROM_BE (bframe->time);
|
||||||
|
#else
|
||||||
|
gint64 atime = GINT64_FROM_LE (aframe->time);
|
||||||
|
gint64 btime = GINT64_FROM_LE (bframe->time);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (atime < btime)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (atime > btime)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (aframe->type == SYSPROF_CAPTURE_FRAME_MARK && bframe->type == SYSPROF_CAPTURE_FRAME_MARK)
|
||||||
|
{
|
||||||
|
const SysprofCaptureMark *amark = (const SysprofCaptureMark *)aframe;
|
||||||
|
const SysprofCaptureMark *bmark = (const SysprofCaptureMark *)bframe;
|
||||||
|
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||||
|
gint64 aduration = GINT64_FROM_BE (amark->duration);
|
||||||
|
gint64 bduration = GINT64_FROM_BE (bmark->duration);
|
||||||
|
#else
|
||||||
|
gint64 aduration = GINT64_FROM_LE (amark->duration);
|
||||||
|
gint64 bduration = GINT64_FROM_LE (bmark->duration);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (aduration > bduration)
|
||||||
|
return -1;
|
||||||
|
else if (aduration < bduration)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sysprof_document_load_worker (GTask *task,
|
sysprof_document_load_worker (GTask *task,
|
||||||
gpointer source_object,
|
gpointer source_object,
|
||||||
@ -830,11 +904,8 @@ sysprof_document_load_worker (GTask *task,
|
|||||||
pos = sizeof self->header;
|
pos = sizeof self->header;
|
||||||
while (pos < (len - sizeof(guint16)))
|
while (pos < (len - sizeof(guint16)))
|
||||||
{
|
{
|
||||||
const SysprofCaptureFrame *tainted;
|
|
||||||
SysprofDocumentFramePointer ptr;
|
SysprofDocumentFramePointer ptr;
|
||||||
gint64 t;
|
|
||||||
guint16 frame_len;
|
guint16 frame_len;
|
||||||
int pid;
|
|
||||||
|
|
||||||
memcpy (&frame_len, &self->base[pos], sizeof frame_len);
|
memcpy (&frame_len, &self->base[pos], sizeof frame_len);
|
||||||
if (self->needs_swap)
|
if (self->needs_swap)
|
||||||
@ -856,10 +927,32 @@ sysprof_document_load_worker (GTask *task,
|
|||||||
ptr.offset = pos;
|
ptr.offset = pos;
|
||||||
ptr.length = frame_len;
|
ptr.length = frame_len;
|
||||||
|
|
||||||
tainted = (const SysprofCaptureFrame *)(gpointer)&self->base[pos];
|
pos += frame_len;
|
||||||
|
count++;
|
||||||
|
|
||||||
pid = self->needs_swap ? GUINT32_SWAP_LE_BE (tainted->pid) : tainted->pid;
|
g_array_append_val (self->frames, ptr);
|
||||||
t = self->needs_swap ? GUINT64_SWAP_LE_BE (tainted->time) : tainted->time;
|
|
||||||
|
if (count % 100 == 0)
|
||||||
|
load_progress (load,
|
||||||
|
(pos / (double)len) * .4,
|
||||||
|
_("Indexing capture data frames"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now sort all the items by their respective frame times as frames
|
||||||
|
* cat into the writer may be tacked on at the end even though they
|
||||||
|
* have state which belongs earlier in the capture.
|
||||||
|
*/
|
||||||
|
if G_UNLIKELY (self->needs_swap)
|
||||||
|
g_array_sort_with_data (self->frames, sort_by_time_swapped, (gpointer)self->base);
|
||||||
|
else
|
||||||
|
g_array_sort_with_data (self->frames, sort_by_time, (gpointer)self->base);
|
||||||
|
|
||||||
|
for (guint f = 0; f < self->frames->len; f++)
|
||||||
|
{
|
||||||
|
SysprofDocumentFramePointer *ptr = &g_array_index (self->frames, SysprofDocumentFramePointer, f);
|
||||||
|
const SysprofCaptureFrame *tainted = (const SysprofCaptureFrame *)(gpointer)&self->base[ptr->offset];
|
||||||
|
gint64 t = self->needs_swap ? GUINT64_SWAP_LE_BE (tainted->time) : tainted->time;
|
||||||
|
int pid = self->needs_swap ? GUINT32_SWAP_LE_BE (tainted->pid) : tainted->pid;
|
||||||
|
|
||||||
if (t > guessed_end_nsec && is_data_type (tainted->type))
|
if (t > guessed_end_nsec && is_data_type (tainted->type))
|
||||||
guessed_end_nsec = t;
|
guessed_end_nsec = t;
|
||||||
@ -869,45 +962,45 @@ sysprof_document_load_worker (GTask *task,
|
|||||||
switch ((int)tainted->type)
|
switch ((int)tainted->type)
|
||||||
{
|
{
|
||||||
case SYSPROF_CAPTURE_FRAME_ALLOCATION:
|
case SYSPROF_CAPTURE_FRAME_ALLOCATION:
|
||||||
egg_bitset_add (self->allocations, self->frames->len);
|
egg_bitset_add (self->allocations, f);
|
||||||
egg_bitset_add (self->traceables, self->frames->len);
|
egg_bitset_add (self->traceables, f);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SYSPROF_CAPTURE_FRAME_SAMPLE:
|
case SYSPROF_CAPTURE_FRAME_SAMPLE:
|
||||||
egg_bitset_add (self->samples, self->frames->len);
|
egg_bitset_add (self->samples, f);
|
||||||
egg_bitset_add (self->traceables, self->frames->len);
|
egg_bitset_add (self->traceables, f);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SYSPROF_CAPTURE_FRAME_PROCESS:
|
case SYSPROF_CAPTURE_FRAME_PROCESS:
|
||||||
egg_bitset_add (self->processes, self->frames->len);
|
egg_bitset_add (self->processes, f);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SYSPROF_CAPTURE_FRAME_FILE_CHUNK:
|
case SYSPROF_CAPTURE_FRAME_FILE_CHUNK:
|
||||||
egg_bitset_add (self->file_chunks, self->frames->len);
|
egg_bitset_add (self->file_chunks, f);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SYSPROF_CAPTURE_FRAME_CTRDEF:
|
case SYSPROF_CAPTURE_FRAME_CTRDEF:
|
||||||
egg_bitset_add (self->ctrdefs, self->frames->len);
|
egg_bitset_add (self->ctrdefs, f);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SYSPROF_CAPTURE_FRAME_CTRSET:
|
case SYSPROF_CAPTURE_FRAME_CTRSET:
|
||||||
egg_bitset_add (self->ctrsets, self->frames->len);
|
egg_bitset_add (self->ctrsets, f);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SYSPROF_CAPTURE_FRAME_MARK:
|
case SYSPROF_CAPTURE_FRAME_MARK:
|
||||||
egg_bitset_add (self->marks, self->frames->len);
|
egg_bitset_add (self->marks, f);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SYSPROF_CAPTURE_FRAME_JITMAP:
|
case SYSPROF_CAPTURE_FRAME_JITMAP:
|
||||||
egg_bitset_add (self->jitmaps, self->frames->len);
|
egg_bitset_add (self->jitmaps, f);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SYSPROF_CAPTURE_FRAME_MAP:
|
case SYSPROF_CAPTURE_FRAME_MAP:
|
||||||
egg_bitset_add (self->mmaps, self->frames->len);
|
egg_bitset_add (self->mmaps, f);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SYSPROF_CAPTURE_FRAME_OVERLAY:
|
case SYSPROF_CAPTURE_FRAME_OVERLAY:
|
||||||
egg_bitset_add (self->overlays, self->frames->len);
|
egg_bitset_add (self->overlays, f);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -922,13 +1015,13 @@ sysprof_document_load_worker (GTask *task,
|
|||||||
!g_hash_table_contains (self->files_first_position, file_chunk->path))
|
!g_hash_table_contains (self->files_first_position, file_chunk->path))
|
||||||
g_hash_table_insert (self->files_first_position,
|
g_hash_table_insert (self->files_first_position,
|
||||||
g_strdup (file_chunk->path),
|
g_strdup (file_chunk->path),
|
||||||
GUINT_TO_POINTER (self->frames->len));
|
GUINT_TO_POINTER (f));
|
||||||
}
|
}
|
||||||
else if (tainted->type == SYSPROF_CAPTURE_FRAME_SAMPLE)
|
else if (tainted->type == SYSPROF_CAPTURE_FRAME_SAMPLE)
|
||||||
{
|
{
|
||||||
const SysprofCaptureSample *sample = (const SysprofCaptureSample *)tainted;
|
const SysprofCaptureSample *sample = (const SysprofCaptureSample *)tainted;
|
||||||
guint n_addrs = self->needs_swap ? GUINT16_SWAP_LE_BE (sample->n_addrs) : sample->n_addrs;
|
guint n_addrs = self->needs_swap ? GUINT16_SWAP_LE_BE (sample->n_addrs) : sample->n_addrs;
|
||||||
const guint8 *endptr = (const guint8 *)tainted + frame_len;
|
const guint8 *endptr = (const guint8 *)tainted + ptr->length;
|
||||||
|
|
||||||
/* If the sample contains a context-switch, record it */
|
/* If the sample contains a context-switch, record it */
|
||||||
if ((const guint8 *)sample + (n_addrs * sizeof (SysprofAddress)) <= endptr)
|
if ((const guint8 *)sample + (n_addrs * sizeof (SysprofAddress)) <= endptr)
|
||||||
@ -942,7 +1035,7 @@ sysprof_document_load_worker (GTask *task,
|
|||||||
if (sysprof_address_is_context_switch (addr, &last_context) &&
|
if (sysprof_address_is_context_switch (addr, &last_context) &&
|
||||||
last_context == SYSPROF_ADDRESS_CONTEXT_KERNEL)
|
last_context == SYSPROF_ADDRESS_CONTEXT_KERNEL)
|
||||||
{
|
{
|
||||||
egg_bitset_add (self->samples_with_context_switch, self->frames->len);
|
egg_bitset_add (self->samples_with_context_switch, f);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -951,7 +1044,7 @@ sysprof_document_load_worker (GTask *task,
|
|||||||
else if (tainted->type == SYSPROF_CAPTURE_FRAME_MARK)
|
else if (tainted->type == SYSPROF_CAPTURE_FRAME_MARK)
|
||||||
{
|
{
|
||||||
const SysprofCaptureMark *mark = (const SysprofCaptureMark *)tainted;
|
const SysprofCaptureMark *mark = (const SysprofCaptureMark *)tainted;
|
||||||
const char *endptr = (const char *)tainted + frame_len;
|
const char *endptr = (const char *)tainted + ptr->length;
|
||||||
gint64 duration = self->needs_swap ? GUINT64_SWAP_LE_BE (mark->duration) : mark->duration;
|
gint64 duration = self->needs_swap ? GUINT64_SWAP_LE_BE (mark->duration) : mark->duration;
|
||||||
|
|
||||||
if (t + duration > guessed_end_nsec)
|
if (t + duration > guessed_end_nsec)
|
||||||
@ -980,19 +1073,9 @@ sysprof_document_load_worker (GTask *task,
|
|||||||
g_hash_table_insert (names, g_strdup (name), bitset);
|
g_hash_table_insert (names, g_strdup (name), bitset);
|
||||||
}
|
}
|
||||||
|
|
||||||
egg_bitset_add (bitset, self->frames->len);
|
egg_bitset_add (bitset, f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pos += frame_len;
|
|
||||||
count++;
|
|
||||||
|
|
||||||
g_array_append_val (self->frames, ptr);
|
|
||||||
|
|
||||||
if (count % 100 == 0)
|
|
||||||
load_progress (load,
|
|
||||||
(pos / (double)len) * .4,
|
|
||||||
_("Indexing capture data frames"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (guessed_end_nsec != 0)
|
if (guessed_end_nsec != 0)
|
||||||
|
|||||||
Reference in New Issue
Block a user