mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2025-12-31 20:36:25 +00:00
libsysprof: add SysprofCaptureModel
This adds a GListModel that we can use to load capture files. The goal here is to map the entire capture into memory so we can avoid reading lots of buffers. That also allows for the model items to live as long as the model is alive (or underlying file map, really). The next goal is to stack features on top of this such as implementing the callgraph as a filter of the model, or generic filters between the callgraph model and the actual data source model.
This commit is contained in:
@ -3,7 +3,9 @@ libsysprof_c_args = [ '-DSYSPROF_COMPILATION' ]
|
||||
libsysprof_public_sources = [
|
||||
'sysprof-battery-source.c',
|
||||
'sysprof-callgraph-profile.c',
|
||||
'sysprof-capture-frame-object.c',
|
||||
'sysprof-capture-gobject.c',
|
||||
'sysprof-capture-model.c',
|
||||
'sysprof-capture-symbol-resolver.c',
|
||||
'sysprof-control-source.c',
|
||||
'sysprof-diskstat-source.c',
|
||||
@ -36,7 +38,9 @@ libsysprof_public_headers = [
|
||||
'sysprof-battery-source.h',
|
||||
'sysprof-callgraph-profile.h',
|
||||
'sysprof-capture-autocleanups.h',
|
||||
'sysprof-capture-frame-object.h',
|
||||
'sysprof-capture-gobject.h',
|
||||
'sysprof-capture-model.h',
|
||||
'sysprof-capture-symbol-resolver.h',
|
||||
'sysprof-control-source.h',
|
||||
'sysprof-diskstat-source.h',
|
||||
|
||||
29
src/libsysprof/sysprof-capture-frame-object-private.h
Normal file
29
src/libsysprof/sysprof-capture-frame-object-private.h
Normal file
@ -0,0 +1,29 @@
|
||||
/* sysprof-capture-frame-object-private.h
|
||||
*
|
||||
* Copyright 2023 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include "sysprof-capture-frame-object.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
SysprofCaptureFrameObject *sysprof_capture_frame_object_new (GMappedFile *mapped,
|
||||
gconstpointer data,
|
||||
gboolean is_native);
|
||||
|
||||
G_END_DECLS
|
||||
72
src/libsysprof/sysprof-capture-frame-object.c
Normal file
72
src/libsysprof/sysprof-capture-frame-object.c
Normal file
@ -0,0 +1,72 @@
|
||||
/* sysprof-capture-frame-object.c
|
||||
*
|
||||
* Copyright 2023 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "sysprof-capture-frame-object-private.h"
|
||||
|
||||
struct _SysprofCaptureFrameObject
|
||||
{
|
||||
GObject parent_instance;
|
||||
GMappedFile *mapped_file;
|
||||
const SysprofCaptureFrame *frame;
|
||||
guint is_native : 1;
|
||||
};
|
||||
|
||||
G_DEFINE_FINAL_TYPE (SysprofCaptureFrameObject, sysprof_capture_frame_object, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
sysprof_capture_frame_object_finalize (GObject *object)
|
||||
{
|
||||
SysprofCaptureFrameObject *self = (SysprofCaptureFrameObject *)object;
|
||||
|
||||
g_clear_pointer (&self->mapped_file, g_mapped_file_unref);
|
||||
self->frame = NULL;
|
||||
|
||||
G_OBJECT_CLASS (sysprof_capture_frame_object_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_capture_frame_object_class_init (SysprofCaptureFrameObjectClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = sysprof_capture_frame_object_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_capture_frame_object_init (SysprofCaptureFrameObject *self)
|
||||
{
|
||||
}
|
||||
|
||||
SysprofCaptureFrameObject *
|
||||
sysprof_capture_frame_object_new (GMappedFile *mapped_file,
|
||||
gconstpointer data,
|
||||
gboolean is_native)
|
||||
{
|
||||
SysprofCaptureFrameObject *self;
|
||||
|
||||
self = g_object_new (SYSPROF_TYPE_CAPTURE_FRAME_OBJECT, NULL);
|
||||
self->mapped_file = g_mapped_file_ref (mapped_file);
|
||||
self->frame = data;
|
||||
self->is_native = !!is_native;
|
||||
|
||||
return self;
|
||||
}
|
||||
37
src/libsysprof/sysprof-capture-frame-object.h
Normal file
37
src/libsysprof/sysprof-capture-frame-object.h
Normal file
@ -0,0 +1,37 @@
|
||||
/* sysprof-capture-frame-object.h
|
||||
*
|
||||
* Copyright 2023 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include <sysprof-capture.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_CAPTURE_FRAME_OBJECT (sysprof_capture_frame_object_get_type())
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (SysprofCaptureFrameObject, sysprof_capture_frame_object, SYSPROF, CAPTURE_FRAME_OBJECT, GObject)
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
SysprofCaptureFrame *sysprof_capture_frame_object_get_frame (SysprofCaptureFrameObject *self);
|
||||
|
||||
G_END_DECLS
|
||||
165
src/libsysprof/sysprof-capture-model.c
Normal file
165
src/libsysprof/sysprof-capture-model.c
Normal file
@ -0,0 +1,165 @@
|
||||
/* sysprof-capture-model.c
|
||||
*
|
||||
* Copyright 2023 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "sysprof-capture-frame-object-private.h"
|
||||
#include "sysprof-capture-model.h"
|
||||
|
||||
struct _SysprofCaptureModel
|
||||
{
|
||||
GObject parent_instance;
|
||||
GPtrArray *frames;
|
||||
GMappedFile *mapped_file;
|
||||
SysprofCaptureFileHeader header;
|
||||
guint is_native : 1;
|
||||
};
|
||||
|
||||
static GType
|
||||
sysprof_capture_model_get_item_type (GListModel *model)
|
||||
{
|
||||
return SYSPROF_TYPE_CAPTURE_FRAME_OBJECT;
|
||||
}
|
||||
|
||||
static guint
|
||||
sysprof_capture_model_get_n_items (GListModel *model)
|
||||
{
|
||||
return SYSPROF_CAPTURE_MODEL (model)->frames->len;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
sysprof_capture_model_get_item (GListModel *model,
|
||||
guint position)
|
||||
{
|
||||
SysprofCaptureModel *self = SYSPROF_CAPTURE_MODEL (model);
|
||||
|
||||
if (position >= self->frames->len)
|
||||
return NULL;
|
||||
|
||||
return sysprof_capture_frame_object_new (self->mapped_file,
|
||||
g_ptr_array_index (self->frames, position),
|
||||
self->is_native);
|
||||
}
|
||||
|
||||
static void
|
||||
list_model_iface_init (GListModelInterface *iface)
|
||||
{
|
||||
iface->get_item_type = sysprof_capture_model_get_item_type;
|
||||
iface->get_n_items = sysprof_capture_model_get_n_items;
|
||||
iface->get_item = sysprof_capture_model_get_item;
|
||||
}
|
||||
|
||||
G_DEFINE_FINAL_TYPE_WITH_CODE (SysprofCaptureModel, sysprof_capture_model, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, list_model_iface_init))
|
||||
|
||||
static void
|
||||
sysprof_capture_model_finalize (GObject *object)
|
||||
{
|
||||
SysprofCaptureModel *self = (SysprofCaptureModel *)object;
|
||||
|
||||
g_clear_pointer (&self->mapped_file, g_mapped_file_unref);
|
||||
g_clear_pointer (&self->frames, g_ptr_array_unref);
|
||||
|
||||
G_OBJECT_CLASS (sysprof_capture_model_parent_class)->finalize (object);
|
||||
}
|
||||
static void
|
||||
sysprof_capture_model_class_init (SysprofCaptureModelClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = sysprof_capture_model_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_capture_model_init (SysprofCaptureModel *self)
|
||||
{
|
||||
self->frames = g_ptr_array_new ();
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_capture_model_load (SysprofCaptureModel *self,
|
||||
int capture_fd,
|
||||
GError **error)
|
||||
{
|
||||
const guint8 *data;
|
||||
goffset pos;
|
||||
gsize len;
|
||||
|
||||
g_assert (SYSPROF_IS_CAPTURE_MODEL (self));
|
||||
g_assert (capture_fd > -1);
|
||||
|
||||
if (!(self->mapped_file = g_mapped_file_new_from_fd (capture_fd, FALSE, error)))
|
||||
return FALSE;
|
||||
|
||||
data = (const guint8 *)g_mapped_file_get_contents (self->mapped_file);
|
||||
len = g_mapped_file_get_length (self->mapped_file);
|
||||
|
||||
if (len < sizeof self->header)
|
||||
return FALSE;
|
||||
|
||||
/* Keep a copy of our header */
|
||||
memcpy (&self->header, data, sizeof self->header);
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
self->is_native = !!self->header.little_endian;
|
||||
#else
|
||||
self->is_native = !self->header.little_endian;
|
||||
#endif
|
||||
|
||||
if (!self->is_native)
|
||||
{
|
||||
self->header.time = GUINT64_SWAP_LE_BE (self->header.time);
|
||||
self->header.end_time = GUINT64_SWAP_LE_BE (self->header.end_time);
|
||||
}
|
||||
|
||||
pos = sizeof self->header;
|
||||
while (pos < (len - sizeof(guint16)))
|
||||
{
|
||||
guint16 frame_len;
|
||||
|
||||
memcpy (&frame_len, &data[pos], sizeof frame_len);
|
||||
if (!self->is_native)
|
||||
frame_len = GUINT16_SWAP_LE_BE (self->is_native);
|
||||
|
||||
if (frame_len < sizeof (SysprofCaptureFrame))
|
||||
break;
|
||||
|
||||
g_ptr_array_add (self->frames, (gpointer)&data[pos]);
|
||||
|
||||
pos += frame_len;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
SysprofCaptureModel *
|
||||
sysprof_capture_model_new_from_fd (int capture_fd,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(SysprofCaptureModel) self = NULL;
|
||||
|
||||
g_return_val_if_fail (capture_fd > -1, NULL);
|
||||
|
||||
self = g_object_new (SYSPROF_TYPE_CAPTURE_MODEL, NULL);
|
||||
|
||||
if (!sysprof_capture_model_load (self, capture_fd, error))
|
||||
return NULL;
|
||||
|
||||
return g_steal_pointer (&self);
|
||||
}
|
||||
38
src/libsysprof/sysprof-capture-model.h
Normal file
38
src/libsysprof/sysprof-capture-model.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* sysprof-capture-model.h
|
||||
*
|
||||
* Copyright 2023 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include <sysprof-capture.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_CAPTURE_MODEL (sysprof_capture_model_get_type())
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (SysprofCaptureModel, sysprof_capture_model, SYSPROF, CAPTURE_MODEL, GObject)
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
SysprofCaptureModel *sysprof_capture_model_new_from_fd (int capture_fd,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
@ -28,7 +28,9 @@ G_BEGIN_DECLS
|
||||
# include "sysprof-battery-source.h"
|
||||
# include "sysprof-callgraph-profile.h"
|
||||
# include "sysprof-capture-autocleanups.h"
|
||||
# include "sysprof-capture-frame-object.h"
|
||||
# include "sysprof-capture-gobject.h"
|
||||
# include "sysprof-capture-model.h"
|
||||
# include "sysprof-capture-symbol-resolver.h"
|
||||
# include "sysprof-control-source.h"
|
||||
# include "sysprof-diskstat-source.h"
|
||||
|
||||
@ -56,6 +56,11 @@ if get_option('libsysprof')
|
||||
dependencies: test_deps,
|
||||
)
|
||||
|
||||
test_capture_model = executable('test-capture-model', 'test-capture-model.c',
|
||||
c_args: test_cflags,
|
||||
dependencies: test_deps,
|
||||
)
|
||||
|
||||
test_mountinfo = executable('test-mountinfo', 'test-mountinfo.c',
|
||||
c_args: test_cflags,
|
||||
dependencies: test_deps,
|
||||
|
||||
56
src/tests/test-capture-model.c
Normal file
56
src/tests/test-capture-model.c
Normal file
@ -0,0 +1,56 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <sysprof.h>
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
SysprofCaptureModel *model;
|
||||
const char *filename;
|
||||
GError *error = NULL;
|
||||
guint n_items;
|
||||
int fd;
|
||||
|
||||
sysprof_clock_init ();
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
g_printerr ("usage: %s FILENAME\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
filename = argv[1];
|
||||
fd = open (filename, O_RDONLY|O_CLOEXEC);
|
||||
|
||||
if (fd == -1)
|
||||
{
|
||||
g_printerr ("Failed to open %s: %s\n",
|
||||
filename, g_strerror (errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(model = sysprof_capture_model_new_from_fd (fd, &error)))
|
||||
{
|
||||
g_printerr ("Failed to load %s: %s\n",
|
||||
filename, error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
n_items = g_list_model_get_n_items (G_LIST_MODEL (model));
|
||||
|
||||
g_print ("%u frames\n", n_items);
|
||||
|
||||
for (guint i = 0; i < n_items; i++)
|
||||
{
|
||||
SysprofCaptureFrameObject *obj = g_list_model_get_item (G_LIST_MODEL (model), i);
|
||||
|
||||
g_clear_object (&obj);
|
||||
}
|
||||
|
||||
close (fd);
|
||||
g_clear_object (&model);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user