Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package gom for openSUSE:Factory checked in at 2024-04-12 17:33:46 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/gom (Old) and /work/SRC/openSUSE:Factory/.gom.new.26366 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "gom" Fri Apr 12 17:33:46 2024 rev:10 rq:1166853 version:0.5.1 Changes: -------- --- /work/SRC/openSUSE:Factory/gom/gom.changes 2024-03-20 21:12:08.993109247 +0100 +++ /work/SRC/openSUSE:Factory/.gom.new.26366/gom.changes 2024-04-12 17:33:57.889939809 +0200 @@ -1,0 +2,9 @@ +Thu Apr 11 11:31:40 UTC 2024 - Dominique Leuenberger <[email protected]> + +- Update to version 0.5.1: + + Reduce object inflation overhead in GType system usage. + + Avoid some allocations in hot paths. + + Avoid hashtables for resourcegroup items. + + Avoid use of weak pointers when unnecessary. + +------------------------------------------------------------------- Old: ---- gom-0.5.0.tar.xz New: ---- gom-0.5.1.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ gom.spec ++++++ --- /var/tmp/diff_new_pack.9vXsA8/_old 2024-04-12 17:33:59.157986509 +0200 +++ /var/tmp/diff_new_pack.9vXsA8/_new 2024-04-12 17:33:59.157986509 +0200 @@ -17,7 +17,7 @@ Name: gom -Version: 0.5.0 +Version: 0.5.1 Release: 0 Summary: GObject Data Mapper License: LGPL-2.1-or-later ++++++ gom-0.5.0.tar.xz -> gom-0.5.1.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gom-0.5.0/NEWS new/gom-0.5.1/NEWS --- old/gom-0.5.0/NEWS 2024-03-03 23:53:47.000000000 +0100 +++ new/gom-0.5.1/NEWS 2024-04-11 01:57:03.000000000 +0200 @@ -1,5 +1,12 @@ Major changes in version +0.5.1 +--- +- Reduce object inflation overhead in GType system usage +- Avoid some allocations in hot paths +- Avoid hashtables for resourcegroup items +- Avoid use of weak pointers when unnecessary + 0.5 --- - Add missing cleanup attribute for GomSorting diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gom-0.5.0/gom/gom-repository-private.h new/gom-0.5.1/gom/gom-repository-private.h --- old/gom-0.5.0/gom/gom-repository-private.h 1970-01-01 01:00:00.000000000 +0100 +++ new/gom-0.5.1/gom/gom-repository-private.h 2024-04-11 01:57:03.000000000 +0200 @@ -0,0 +1,28 @@ +/* gom-repository-private.h + * + * Copyright (C) 2024 Christian Hergert <[email protected]> + * + * This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This file 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 + * Lesser 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/>. + */ + +#include "gom-repository.h" + +G_BEGIN_DECLS + +void _gom_repository_observe (GomRepository *repository, + GList *link); +void _gom_repository_unobserve (GomRepository *repository, + GList *link); + +G_END_DECLS diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gom-0.5.0/gom/gom-repository.c new/gom-0.5.1/gom/gom-repository.c --- old/gom-0.5.0/gom/gom-repository.c 2024-03-03 23:53:47.000000000 +0100 +++ new/gom-0.5.1/gom/gom-repository.c 2024-04-11 01:57:03.000000000 +0200 @@ -20,11 +20,15 @@ #include "gom-command-builder.h" #include "gom-cursor.h" #include "gom-error.h" -#include "gom-repository.h" +#include "gom-repository-private.h" +#include "gom-resource-private.h" struct _GomRepositoryPrivate { GomAdapter *adapter; + + GMutex mutex; + GQueue observed; }; G_DEFINE_TYPE_WITH_PRIVATE(GomRepository, gom_repository, G_TYPE_OBJECT) @@ -866,9 +870,17 @@ gom_repository_finalize (GObject *object) { GomRepositoryPrivate *priv = GOM_REPOSITORY(object)->priv; + GList *link; g_clear_object(&priv->adapter); + while ((link = priv->observed.head)) { + g_queue_unlink (&priv->observed, link); + _gom_resource_weak_notify (link->data); + } + + g_mutex_clear (&priv->mutex); + G_OBJECT_CLASS(gom_repository_parent_class)->finalize(object); } @@ -960,4 +972,30 @@ gom_repository_init (GomRepository *repository) { repository->priv = gom_repository_get_instance_private(repository); + + g_mutex_clear (&repository->priv->mutex); +} + +void +_gom_repository_observe (GomRepository *repository, + GList *link) +{ + g_assert (GOM_IS_REPOSITORY (repository)); + g_assert (link != NULL); + + g_mutex_lock (&repository->priv->mutex); + g_queue_push_tail_link (&repository->priv->observed, link); + g_mutex_unlock (&repository->priv->mutex); +} + +void +_gom_repository_unobserve (GomRepository *repository, + GList *link) +{ + g_assert (GOM_IS_REPOSITORY (repository)); + g_assert (link != NULL); + + g_mutex_lock (&repository->priv->mutex); + g_queue_unlink (&repository->priv->observed, link); + g_mutex_unlock (&repository->priv->mutex); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gom-0.5.0/gom/gom-resource-group.c new/gom-0.5.1/gom/gom-resource-group.c --- old/gom-0.5.0/gom/gom-resource-group.c 2024-03-03 23:53:47.000000000 +0100 +++ new/gom-0.5.1/gom/gom-resource-group.c 2024-04-11 01:57:03.000000000 +0200 @@ -63,10 +63,27 @@ }; typedef struct { - GomResource *resource; - GHashTable *ht; + union { + /* When inflated == TRUE, this is the resource */ + GomResource *resource; + + /* When inflated == FALSE, this is the array of + * parameters to be inflated. It is always allocated + * with an extra parameter at the end that can be + * used for inflation of repository property. + */ + GParameter *params; + }; + guint inflated : 1; + guint n_params : 31; } ItemData; +typedef struct { + GParamSpec *pspec; + GomResourceFromBytesFunc from_bytes_func; + guint column; +} CursorMapping; + static GParamSpec *gParamSpecs[LAST_PROP]; GomResourceGroup * @@ -83,7 +100,7 @@ gboolean gom_resource_group_append (GomResourceGroup *group, - GomResource *resource) + GomResource *resource) { g_return_val_if_fail(GOM_IS_RESOURCE_GROUP(group), FALSE); g_return_val_if_fail(GOM_IS_RESOURCE(resource), FALSE); @@ -552,33 +569,22 @@ } static void -value_free (gpointer data) -{ - GValue *value = data; - - if (value == NULL) - return; - g_value_unset(value); - g_free(value); -} - -static void item_data_free (gpointer data) { ItemData *itemdata = data; - if (itemdata == NULL) - return; - g_clear_object(&itemdata->resource); - g_clear_pointer(&itemdata->ht, g_hash_table_destroy); - g_free (itemdata); -} -static void -foreach_prop (gpointer key, - gpointer value, - gpointer user_data) -{ - g_object_set_property(user_data, key, value); + if (itemdata != NULL) { + if (itemdata->inflated) { + g_clear_object(&itemdata->resource); + } else { + for (guint i = 0; i < itemdata->n_params; i++) { + g_value_unset (&itemdata->params[i].value); + } + g_free (itemdata->params); + } + + g_free (itemdata); + } } static void @@ -586,67 +592,96 @@ GType resource_type, GomRepository *repository) { - if (itemdata->resource) + GomResource *resource; + + g_assert (itemdata != NULL); + g_assert (!itemdata->inflated || GOM_IS_RESOURCE (itemdata->resource)); + + if (itemdata->inflated) return; - itemdata->resource = g_object_new(resource_type, - "repository", repository, - NULL); - g_hash_table_foreach(itemdata->ht, foreach_prop, itemdata->resource); - gom_resource_set_is_from_table(itemdata->resource, TRUE); - g_clear_pointer(&itemdata->ht, g_hash_table_destroy); + itemdata->params[itemdata->n_params].name = "repository"; + g_value_init (&itemdata->params[itemdata->n_params].value, GOM_TYPE_REPOSITORY); + g_value_set_object (&itemdata->params[itemdata->n_params].value, repository); + + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + resource = g_object_newv (resource_type, + itemdata->n_params + 1, + itemdata->params); + G_GNUC_END_IGNORE_DEPRECATIONS + gom_resource_set_is_from_table(resource, TRUE); + + for (guint i = 0; i < itemdata->n_params + 1; i++) { + g_value_unset (&itemdata->params[i].value); + } + g_free (itemdata->params); + + itemdata->resource = resource; + itemdata->inflated = TRUE; } -static ItemData * -set_props (GType resource_type, - GomCursor *cursor) +static void +discover_cursor_mapping (GType resource_type, + GomCursor *cursor, + CursorMapping *mappings, + guint *n_mappings) { - GObjectClass *klass; - const gchar *name; - GParamSpec *pspec; - guint n_cols; - guint i; - GHashTable *ht; - ItemData *itemdata; + GObjectClass *klass = g_type_class_ref(resource_type); + guint n_cols = gom_cursor_get_n_columns (cursor); + guint j = 0; - g_assert(GOM_IS_CURSOR(cursor)); - - klass = g_type_class_ref(resource_type); - n_cols = gom_cursor_get_n_columns(cursor); - ht = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, value_free); + for (guint i = 0; i < n_cols; i++) { + const char *name = gom_cursor_get_column_name(cursor, i); + GParamSpec *pspec; - for (i = 0; i < n_cols; i++) { - name = gom_cursor_get_column_name(cursor, i); if ((pspec = g_object_class_find_property(klass, name))) { - GomResourceFromBytesFunc from_bytes; - - from_bytes = g_param_spec_get_qdata(pspec, GOM_RESOURCE_FROM_BYTES_FUNC); - if (from_bytes) { - GValue *converted; - GValue value = { 0, }; - - converted = g_new0 (GValue, 1); - g_value_init(&value, G_TYPE_BYTES); - gom_cursor_get_column(cursor, i, &value); - (*from_bytes) (g_value_get_boxed(&value), converted); - g_value_unset(&value); - g_hash_table_insert(ht, g_strdup(name), converted); - } else { - GValue *value; - - value = g_new0 (GValue, 1); - g_value_init(value, pspec->value_type); - gom_cursor_get_column(cursor, i, value); - g_hash_table_insert(ht, g_strdup(name), value); - } + mappings[j].pspec = pspec; + mappings[j].column = i; + mappings[j].from_bytes_func = g_param_spec_get_qdata(pspec, GOM_RESOURCE_FROM_BYTES_FUNC); + j++; } } - g_type_class_unref (klass); + *n_mappings = j; + + g_clear_pointer (&klass, g_type_class_unref); +} + +static ItemData * +set_props (GType resource_type, + GomCursor *cursor, + CursorMapping *mappings, + guint n_mappings) +{ + ItemData *itemdata; + + g_assert(GOM_IS_CURSOR(cursor)); - itemdata = g_new0(ItemData, 1); - itemdata->ht = ht; + itemdata = g_new (ItemData, 1); + itemdata->inflated = FALSE; + /* Always include an extra GParameter so that we may + * add the GomRepository at the end. + */ + itemdata->params = g_new0 (GParameter, n_mappings + 1); + itemdata->n_params = n_mappings; + + for (guint i = 0; i < n_mappings; i++) { + const CursorMapping *map = &mappings[i]; + + itemdata->params[i].name = map->pspec->name; + + if G_UNLIKELY (map->from_bytes_func != NULL) { + GValue value = G_VALUE_INIT; + + g_value_init(&value, G_TYPE_BYTES); + gom_cursor_get_column(cursor, i, &value); + (*map->from_bytes_func) (g_value_get_boxed(&value), &itemdata->params[i].value); + g_value_unset(&value); + } else { + g_value_init(&itemdata->params[i].value, map->pspec->value_type); + gom_cursor_get_column(cursor, i, &itemdata->params[i].value); + } + } return itemdata; } @@ -672,6 +707,8 @@ GomCursor *cursor = NULL; GomFilter *filter = NULL; GomSorting *sorting = NULL; + CursorMapping mappings_stack[32]; + CursorMapping *mappings = mappings_stack; GError *error = NULL; GType resource_type; gchar *m2m_table = NULL; @@ -679,6 +716,7 @@ guint limit; guint offset; guint idx; + guint n_mappings = 0; GAsyncQueue *queue; g_return_if_fail(GOM_IS_ADAPTER(adapter)); @@ -736,8 +774,14 @@ idx = offset; ht = g_hash_table_new(NULL, NULL); + if (gom_cursor_get_n_columns (cursor) > G_N_ELEMENTS (mappings_stack)) { + mappings = g_new (CursorMapping, gom_cursor_get_n_columns (cursor)); + } + + discover_cursor_mapping (resource_type, cursor, mappings, &n_mappings); + while (gom_cursor_next(cursor)) { - ItemData *itemdata = set_props(resource_type, cursor); + ItemData *itemdata = set_props(resource_type, cursor, mappings, n_mappings); g_hash_table_insert(ht, GUINT_TO_POINTER(idx), itemdata); idx++; } @@ -749,6 +793,9 @@ g_simple_async_result_set_op_res_gboolean(simple, TRUE); out: + if (mappings != mappings_stack) + g_free (mappings); + g_object_unref(group); g_clear_object(&builder); g_clear_object(&command); @@ -895,6 +942,7 @@ goto unlock; } item_data_ensure_resource(itemdata, priv->resource_type, priv->repository); + g_assert (itemdata->inflated); ret = itemdata->resource; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gom-0.5.0/gom/gom-resource-private.h new/gom-0.5.1/gom/gom-resource-private.h --- old/gom-0.5.0/gom/gom-resource-private.h 1970-01-01 01:00:00.000000000 +0100 +++ new/gom-0.5.1/gom/gom-resource-private.h 2024-04-11 01:57:03.000000000 +0200 @@ -0,0 +1,25 @@ +/* gom-resource-private.h + * + * Copyright (C) 2011 Christian Hergert <[email protected]> + * + * This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This file 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 + * Lesser 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/>. + */ + +#include "gom-resource.h" + +G_BEGIN_DECLS + +void _gom_resource_weak_notify (GomResource *resource); + +G_END_DECLS diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gom-0.5.0/gom/gom-resource.c new/gom-0.5.1/gom/gom-resource.c --- old/gom-0.5.0/gom/gom-resource.c 2024-03-03 23:53:47.000000000 +0100 +++ new/gom-0.5.1/gom/gom-resource.c 2024-04-11 01:57:03.000000000 +0200 @@ -24,6 +24,7 @@ #include "gom-error.h" #include "gom-filter.h" #include "gom-repository.h" +#include "gom-repository-private.h" #include "gom-resource.h" #include "gom-resource-priv.h" #include "reserved-keywords.h" @@ -31,6 +32,7 @@ struct _GomResourcePrivate { GomRepository *repository; + GList link; gboolean is_from_table; }; @@ -287,20 +289,19 @@ priv = resource->priv; + if (priv->repository == repository) + return; + old = priv->repository; - if (old) { - g_object_remove_weak_pointer(G_OBJECT(priv->repository), - (gpointer *)&priv->repository); - priv->repository = NULL; - } + priv->repository = repository; - if (repository) { - priv->repository = repository; - g_object_add_weak_pointer(G_OBJECT(priv->repository), - (gpointer *)&priv->repository); - g_object_notify_by_pspec(G_OBJECT(resource), - gParamSpecs[PROP_REPOSITORY]); - } + if (old) + _gom_repository_unobserve (old, &priv->link); + + if (repository) + _gom_repository_observe (repository, &priv->link); + + g_object_notify_by_pspec (G_OBJECT (resource), gParamSpecs[PROP_REPOSITORY]); } gboolean @@ -981,19 +982,18 @@ return group ? g_object_ref(group) : NULL; } -/** - * gom_resource_finalize: - * @object: (in): A #GomResource. - * - * Finalizer for a #GomResource instance. Frees any resources held by - * the instance. - */ static void -gom_resource_finalize (GObject *object) +gom_resource_dispose (GObject *object) { GomResource *resource = (GomResource *) object; - gom_resource_set_repository(resource, NULL); - G_OBJECT_CLASS(gom_resource_parent_class)->finalize(object); + + if (resource->priv->repository) { + _gom_repository_unobserve (resource->priv->repository, + &resource->priv->link); + resource->priv->repository = NULL; + } + + G_OBJECT_CLASS(gom_resource_parent_class)->dispose (object); } /** @@ -1064,16 +1064,16 @@ static void gom_resource_constructed (GObject *object) { - char *pkey_signal; GomResourceClass *klass; + char signal_key[128]; /* Monitor the primary key */ klass = GOM_RESOURCE_CLASS (G_OBJECT_GET_CLASS(object)); g_assert (klass->primary_key[0] != '\0'); - pkey_signal = g_strdup_printf("notify::%s", klass->primary_key); - g_signal_connect (G_OBJECT (object), pkey_signal, + memcpy (signal_key, "notify::", 8); + g_strlcat (&signal_key[8], klass->primary_key, sizeof signal_key - 8); + g_signal_connect (G_OBJECT (object), signal_key, G_CALLBACK (pkey_changed_cb), NULL); - g_free(pkey_signal); G_OBJECT_CLASS (gom_resource_parent_class)->constructed (object); } @@ -1090,7 +1090,7 @@ GObjectClass *object_class; object_class = G_OBJECT_CLASS(klass); - object_class->finalize = gom_resource_finalize; + object_class->dispose = gom_resource_dispose; object_class->get_property = gom_resource_get_property; object_class->set_property = gom_resource_set_property; object_class->constructed = gom_resource_constructed; @@ -1115,6 +1115,7 @@ gom_resource_init (GomResource *resource) { resource->priv = gom_resource_get_instance_private(resource); + resource->priv->link.data = resource; } gboolean @@ -1177,3 +1178,10 @@ { return g_quark_from_static_string("gom_resource_notnull"); } + +void +_gom_resource_weak_notify (GomResource *resource) +{ + GomResourcePrivate *priv = resource->priv; + priv->repository = NULL; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gom-0.5.0/gom/meson.build new/gom-0.5.1/gom/meson.build --- old/gom-0.5.0/gom/meson.build 2024-03-03 23:53:47.000000000 +0100 +++ new/gom-0.5.1/gom/meson.build 2024-04-11 01:57:03.000000000 +0200 @@ -34,9 +34,15 @@ install_headers(gom_headers, subdir: '@0@/@1@'.format(lib_name, meson.project_name())) +libgom_c_args = [ + '-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_@0@_@1@'.format(glib2_major_version, glib2_minor_version), + '-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_@0@_@1@'.format(glib2_major_version, glib2_minor_version), +] + libgom = shared_library(lib_name, sources: gom_sources + gom_private_headers, install: true, + c_args: libgom_c_args, soversion: soversion, version: lt_version, dependencies: [gio_dep, glib_dep, gobject_dep, sqlite3_dep]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gom-0.5.0/meson.build new/gom-0.5.1/meson.build --- old/gom-0.5.0/meson.build 2024-03-03 23:53:47.000000000 +0100 +++ new/gom-0.5.1/meson.build 2024-04-11 01:57:03.000000000 +0200 @@ -1,5 +1,5 @@ project('gom', 'c', - version: '0.5.0', + version: '0.5.1', license: 'LGPL-2.1+', meson_version: '>= 0.48') @@ -17,7 +17,10 @@ enable_gir = get_option('enable-introspection') enable_gtkdoc = get_option('enable-gtk-doc') -glib2_required = '>= 2.38' +glib2_req_version = '2.38' +glib2_major_version = glib2_req_version.split('.')[0] +glib2_minor_version = glib2_req_version.split('.')[1] +glib2_required = '>= @0@'.format(glib2_req_version) gio_dep = dependency('gio-2.0', version: glib2_required) glib_dep = dependency('glib-2.0', version: glib2_required)
