Merge branch 'th/gobj-performance-fixes' into 'main'

[th/gobj-performance-fixes] improvements and fixes for gobject's `performance.c` benchmark

See merge request GNOME/glib!4523
This commit is contained in:
Philip Withnall 2025-02-26 12:12:13 +00:00
commit c73df43854
2 changed files with 57 additions and 37 deletions

View File

@ -11,11 +11,14 @@
# #
# 1) configure the build. For example run # 1) configure the build. For example run
# $ git clean -fdx # $ git clean -fdx
# $ meson build -Dprefix=/tmp/glib/ -Db_lto=true --buildtype release -Ddebug=true # $ meson build -Dprefix=/tmp/glib/ -Db_lto=true --buildtype release -Ddebug=false
# Beware, that running the script will check out other commits, # Beware, that running the script will check out other commits,
# build the tree and run `ninja install`. Don't have important # build the tree and run `ninja install`. Don't have important
# work there. # work there.
# #
# Consider setting `echo performance | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor`
# and check `watch cat /sys/devices/system/cpu/cpu[0-9]*/cpufreq/scaling_cur_freq`.
#
# 2) run the script. Set $COMMITS to the list of commit sha's to test. # 2) run the script. Set $COMMITS to the list of commit sha's to test.
# Environment variables: # Environment variables:
# COMMITS: list of git references to test. # COMMITS: list of git references to test.
@ -33,23 +36,23 @@
# #
# # once: # # once:
# git clean -fdx # git clean -fdx
# meson build -Dprefix=/tmp/glib/ -Db_lto=true --buildtype release -Ddebug=true # meson build -Dprefix=/tmp/glib/ -Db_lto=true --buildtype release -Ddebug=false
# #
# # test: # # test:
# COMMIT_END=my-test-branch # COMMIT_END=my-test-branch
# COMMIT_START="$(git merge-base origin/main "$COMMIT_END")" # COMMIT_START="$(git merge-base origin/main "$COMMIT_END")"
# PERF="" PATCH="" COMMITS=" $COMMIT_START $COMMIT_END " /tmp/performance-run.sh -s 5 # PERF="" PATCH="" COMMITS=" $COMMIT_START $COMMIT_END " /tmp/performance-run.sh -q -s 5
# PERF="" PATCH="" COMMITS=" $COMMIT_START $( git log --reverse --pretty=%H "$COMMIT_START..$COMMIT_END" ) " /tmp/performance-run.sh -s 5 # PERF="" PATCH="" COMMITS=" $COMMIT_START $( git log --reverse --pretty=%H "$COMMIT_START..$COMMIT_END" ) " /tmp/performance-run.sh -q -s 5
# #
# GLIB_PERFORMANCE_FACTOR=17.06 PERF='perf stat -r 3 -B' PATCH="" COMMITS=" $COMMIT_START $COMMIT_END " /tmp/performance-run.sh -s 1 property-get # GLIB_PERFORMANCE_FACTOR=1 PERF='perf stat -r 3 -B' PATCH="" COMMITS=" $COMMIT_START $COMMIT_END " /tmp/performance-run.sh -q -s 1 property-get
set -e set -e
usage() { usage() {
sed -n '4,/^$/ s/^#\( \(.*\)\|\)$/\2/p' "$0" sed -n '/^# Run /,/^$/ s/^#\( \(.*\)\|\)$/\2/p' "$0"
} }
if [ "$#" -eq 1 ] && [ "$1" == "-h" ] ; then if [[ "$#" -eq 1 && ( "$1" == "-h" || "$1" == "--help" ) ]]; then
usage usage
exit 0 exit 0
fi fi
@ -92,7 +95,7 @@ Testing commits:
$(_list_commits " ") $(_list_commits " ")
\$ meson build -Dprefix=/tmp/glib/ -Db_lto=true --buildtype release -Ddebug=true \$ meson build -Dprefix=/tmp/glib/ -Db_lto=true --buildtype release -Ddebug=false
\$ PATCH=$(printf '%q' "$PATCH") \\ \$ PATCH=$(printf '%q' "$PATCH") \\
PREPARE_CMD=$(printf '%q' "$PREPARE_CMD") \\ PREPARE_CMD=$(printf '%q' "$PREPARE_CMD") \\
PERF=$(printf '%q' "$PERF") \\ PERF=$(printf '%q' "$PERF") \\
@ -151,6 +154,7 @@ for idx in "${!COMMITS_V[@]}" ; do
# ./build/gobject/tests/performance/performance # ./build/gobject/tests/performance/performance
# ldd ./build/gobject/tests/performance/performance # ldd ./build/gobject/tests/performance/performance
sleep 2
( (
if [ -z "$PERF" ] ; then if [ -z "$PERF" ] ; then
TESTRUN="$I" TESTCOMMIT="$commit" ./build/gobject/tests/performance/performance "$@" TESTRUN="$I" TESTCOMMIT="$commit" ./build/gobject/tests/performance/performance "$@"

View File

@ -52,8 +52,11 @@ static GOptionEntry cmd_entries[] = {
typedef struct _PerformanceTest PerformanceTest; typedef struct _PerformanceTest PerformanceTest;
struct _PerformanceTest { struct _PerformanceTest {
const char *name; const char *name;
gpointer extra_data; gpointer extra_data;
guint base_factor;
gpointer (*setup) (PerformanceTest *test); gpointer (*setup) (PerformanceTest *test);
void (*init) (PerformanceTest *test, void (*init) (PerformanceTest *test,
gpointer data, gpointer data,
@ -501,8 +504,6 @@ complex_object_init (ComplexObject *complex_object)
* Test object construction performance * Test object construction performance
*************************************************************/ *************************************************************/
#define NUM_OBJECT_TO_CONSTRUCT 10000
struct ConstructionTest { struct ConstructionTest {
GObject **objects; GObject **objects;
unsigned int n_objects; unsigned int n_objects;
@ -528,7 +529,7 @@ test_construction_init (PerformanceTest *test,
struct ConstructionTest *data = _data; struct ConstructionTest *data = _data;
unsigned int n; unsigned int n;
n = (unsigned int) (NUM_OBJECT_TO_CONSTRUCT * count_factor); n = (unsigned int) (test->base_factor * count_factor);
if (data->n_objects != n) if (data->n_objects != n)
{ {
data->n_objects = n; data->n_objects = n;
@ -650,7 +651,7 @@ test_finalization_init (PerformanceTest *test,
struct ConstructionTest *data = _data; struct ConstructionTest *data = _data;
unsigned int n; unsigned int n;
n = (unsigned int) (NUM_OBJECT_TO_CONSTRUCT * count_factor); n = (unsigned int) (test->base_factor * count_factor);
if (data->n_objects != n) if (data->n_objects != n)
{ {
data->n_objects = n; data->n_objects = n;
@ -710,7 +711,10 @@ test_finalization_print_result (PerformanceTest *test,
* Test runtime type check performance * Test runtime type check performance
*************************************************************/ *************************************************************/
#define NUM_KILO_CHECKS_PER_ROUND 50 /* Work around g_type_check_instance_is_a being marked "pure",
* and thus only called once for the loop. */
static gboolean (*my_type_check_instance_is_a) (GTypeInstance *type_instance,
GType iface_type);
struct TypeCheckTest { struct TypeCheckTest {
GObject *object; GObject *object;
@ -722,6 +726,8 @@ test_type_check_setup (PerformanceTest *test)
{ {
struct TypeCheckTest *data; struct TypeCheckTest *data;
my_type_check_instance_is_a = &g_type_check_instance_is_a;
data = g_new0 (struct TypeCheckTest, 1); data = g_new0 (struct TypeCheckTest, 1);
data->object = g_object_new (COMPLEX_TYPE_OBJECT, NULL); data->object = g_object_new (COMPLEX_TYPE_OBJECT, NULL);
@ -735,15 +741,9 @@ test_type_check_init (PerformanceTest *test,
{ {
struct TypeCheckTest *data = _data; struct TypeCheckTest *data = _data;
data->n_checks = (unsigned int) (factor * NUM_KILO_CHECKS_PER_ROUND); data->n_checks = (unsigned int) (test->base_factor * factor);
} }
/* Work around g_type_check_instance_is_a being marked "pure",
and thus only called once for the loop. */
gboolean (*my_type_check_instance_is_a) (GTypeInstance *type_instance,
GType iface_type) = &g_type_check_instance_is_a;
static void static void
test_type_check_run (PerformanceTest *test, test_type_check_run (PerformanceTest *test,
gpointer _data) gpointer _data)
@ -799,8 +799,6 @@ test_type_check_teardown (PerformanceTest *test,
* Test signal emissions performance (common code) * Test signal emissions performance (common code)
*************************************************************/ *************************************************************/
#define NUM_EMISSIONS_PER_ROUND 10000
struct EmissionTest { struct EmissionTest {
GObject *object; GObject *object;
unsigned int n_checks; unsigned int n_checks;
@ -851,7 +849,7 @@ test_emission_unhandled_init (PerformanceTest *test,
{ {
struct EmissionTest *data = _data; struct EmissionTest *data = _data;
data->n_checks = (unsigned int) (factor * NUM_EMISSIONS_PER_ROUND); data->n_checks = (unsigned int) (test->base_factor * factor);
} }
static void static void
@ -924,7 +922,7 @@ test_emission_handled_init (PerformanceTest *test,
{ {
struct EmissionTest *data = _data; struct EmissionTest *data = _data;
data->n_checks = (unsigned int) (factor * NUM_EMISSIONS_PER_ROUND); data->n_checks = (unsigned int) (test->base_factor * factor);
} }
static void static void
@ -958,8 +956,6 @@ test_emission_handled_teardown (PerformanceTest *test,
* Test object notify performance (common code) * Test object notify performance (common code)
*************************************************************/ *************************************************************/
#define NUM_NOTIFY_PER_ROUND 10000
struct NotifyTest { struct NotifyTest {
GObject *object; GObject *object;
unsigned int n_checks; unsigned int n_checks;
@ -1008,7 +1004,7 @@ test_notify_unhandled_init (PerformanceTest *test,
{ {
struct NotifyTest *data = _data; struct NotifyTest *data = _data;
data->n_checks = (unsigned int) (factor * NUM_NOTIFY_PER_ROUND); data->n_checks = (unsigned int) (test->base_factor * factor);
} }
static void static void
@ -1070,7 +1066,7 @@ test_notify_handled_init (PerformanceTest *test,
{ {
struct NotifyTest *data = _data; struct NotifyTest *data = _data;
data->n_checks = (unsigned int) (factor * NUM_NOTIFY_PER_ROUND); data->n_checks = (unsigned int) (test->base_factor * factor);
} }
static void static void
@ -1108,8 +1104,6 @@ test_notify_handled_teardown (PerformanceTest *test,
* Test object set performance * Test object set performance
*************************************************************/ *************************************************************/
#define NUM_SET_PER_ROUND 10000
struct SetTest { struct SetTest {
GObject *object; GObject *object;
unsigned int n_checks; unsigned int n_checks;
@ -1150,7 +1144,7 @@ test_set_init (PerformanceTest *test,
{ {
struct SetTest *data = _data; struct SetTest *data = _data;
data->n_checks = (unsigned int) (factor * NUM_SET_PER_ROUND); data->n_checks = (unsigned int) (test->base_factor * factor);
} }
static void static void
@ -1185,8 +1179,6 @@ test_set_teardown (PerformanceTest *test,
* Test object get performance * Test object get performance
*************************************************************/ *************************************************************/
#define NUM_GET_PER_ROUND 10000
struct GetTest { struct GetTest {
GObject *object; GObject *object;
unsigned int n_checks; unsigned int n_checks;
@ -1228,7 +1220,7 @@ test_get_init (PerformanceTest *test,
{ {
struct GetTest *data = _data; struct GetTest *data = _data;
data->n_checks = (unsigned int) (factor * NUM_GET_PER_ROUND); data->n_checks = (unsigned int) (test->base_factor * factor);
} }
static void static void
@ -1263,8 +1255,6 @@ test_get_teardown (PerformanceTest *test,
* Test object refcount performance * Test object refcount performance
*************************************************************/ *************************************************************/
#define NUM_KILO_REFS_PER_ROUND 100000
struct RefcountTest { struct RefcountTest {
GObject *object; GObject *object;
unsigned int n_checks; unsigned int n_checks;
@ -1303,7 +1293,7 @@ test_refcount_init (PerformanceTest *test,
{ {
struct RefcountTest *data = _data; struct RefcountTest *data = _data;
data->n_checks = (unsigned int) (factor * NUM_KILO_REFS_PER_ROUND); data->n_checks = (unsigned int) (test->base_factor * factor);
} }
static void static void
@ -1381,6 +1371,7 @@ static PerformanceTest tests[] = {
{ {
"simple-construction", "simple-construction",
simple_object_get_type, simple_object_get_type,
347800,
test_construction_setup, test_construction_setup,
test_construction_init, test_construction_init,
test_construction_run, test_construction_run,
@ -1391,6 +1382,7 @@ static PerformanceTest tests[] = {
{ {
"simple-construction1", "simple-construction1",
simple_object_get_type, simple_object_get_type,
1454500,
test_construction_setup, test_construction_setup,
test_construction_init, test_construction_init,
test_construction_run1, test_construction_run1,
@ -1401,6 +1393,7 @@ static PerformanceTest tests[] = {
{ {
"complex-construction", "complex-construction",
complex_object_get_type, complex_object_get_type,
110800,
test_construction_setup, test_construction_setup,
test_construction_init, test_construction_init,
test_complex_construction_run, test_complex_construction_run,
@ -1411,6 +1404,7 @@ static PerformanceTest tests[] = {
{ {
"complex-construction1", "complex-construction1",
complex_object_get_type, complex_object_get_type,
204600,
test_construction_setup, test_construction_setup,
test_construction_init, test_construction_init,
test_complex_construction_run1, test_complex_construction_run1,
@ -1421,6 +1415,7 @@ static PerformanceTest tests[] = {
{ {
"complex-construction2", "complex-construction2",
complex_object_get_type, complex_object_get_type,
237400,
test_construction_setup, test_construction_setup,
test_construction_init, test_construction_init,
test_complex_construction_run2, test_complex_construction_run2,
@ -1431,6 +1426,7 @@ static PerformanceTest tests[] = {
{ {
"finalization", "finalization",
simple_object_get_type, simple_object_get_type,
47400,
test_construction_setup, test_construction_setup,
test_finalization_init, test_finalization_init,
test_finalization_run, test_finalization_run,
@ -1441,6 +1437,7 @@ static PerformanceTest tests[] = {
{ {
"type-check", "type-check",
NULL, NULL,
1887,
test_type_check_setup, test_type_check_setup,
test_type_check_init, test_type_check_init,
test_type_check_run, test_type_check_run,
@ -1451,6 +1448,7 @@ static PerformanceTest tests[] = {
{ {
"emit-unhandled", "emit-unhandled",
GUINT_TO_POINTER (COMPLEX_SIGNAL), GUINT_TO_POINTER (COMPLEX_SIGNAL),
56300,
test_emission_unhandled_setup, test_emission_unhandled_setup,
test_emission_unhandled_init, test_emission_unhandled_init,
test_emission_run, test_emission_run,
@ -1461,6 +1459,7 @@ static PerformanceTest tests[] = {
{ {
"emit-unhandled-empty", "emit-unhandled-empty",
GUINT_TO_POINTER (COMPLEX_SIGNAL_EMPTY), GUINT_TO_POINTER (COMPLEX_SIGNAL_EMPTY),
496900,
test_emission_unhandled_setup, test_emission_unhandled_setup,
test_emission_unhandled_init, test_emission_unhandled_init,
test_emission_run, test_emission_run,
@ -1471,6 +1470,7 @@ static PerformanceTest tests[] = {
{ {
"emit-unhandled-generic", "emit-unhandled-generic",
GUINT_TO_POINTER (COMPLEX_SIGNAL_GENERIC), GUINT_TO_POINTER (COMPLEX_SIGNAL_GENERIC),
71700,
test_emission_unhandled_setup, test_emission_unhandled_setup,
test_emission_unhandled_init, test_emission_unhandled_init,
test_emission_run, test_emission_run,
@ -1481,6 +1481,7 @@ static PerformanceTest tests[] = {
{ {
"emit-unhandled-generic-empty", "emit-unhandled-generic-empty",
GUINT_TO_POINTER (COMPLEX_SIGNAL_GENERIC_EMPTY), GUINT_TO_POINTER (COMPLEX_SIGNAL_GENERIC_EMPTY),
506300,
test_emission_unhandled_setup, test_emission_unhandled_setup,
test_emission_unhandled_init, test_emission_unhandled_init,
test_emission_run, test_emission_run,
@ -1491,6 +1492,7 @@ static PerformanceTest tests[] = {
{ {
"emit-unhandled-args", "emit-unhandled-args",
GUINT_TO_POINTER (COMPLEX_SIGNAL_ARGS), GUINT_TO_POINTER (COMPLEX_SIGNAL_ARGS),
52000,
test_emission_unhandled_setup, test_emission_unhandled_setup,
test_emission_unhandled_init, test_emission_unhandled_init,
test_emission_run_args, test_emission_run_args,
@ -1501,6 +1503,7 @@ static PerformanceTest tests[] = {
{ {
"emit-handled", "emit-handled",
GUINT_TO_POINTER (COMPLEX_SIGNAL), GUINT_TO_POINTER (COMPLEX_SIGNAL),
38600,
test_emission_handled_setup, test_emission_handled_setup,
test_emission_handled_init, test_emission_handled_init,
test_emission_run, test_emission_run,
@ -1511,6 +1514,7 @@ static PerformanceTest tests[] = {
{ {
"emit-handled-empty", "emit-handled-empty",
GUINT_TO_POINTER (COMPLEX_SIGNAL_EMPTY), GUINT_TO_POINTER (COMPLEX_SIGNAL_EMPTY),
40100,
test_emission_handled_setup, test_emission_handled_setup,
test_emission_handled_init, test_emission_handled_init,
test_emission_run, test_emission_run,
@ -1521,6 +1525,7 @@ static PerformanceTest tests[] = {
{ {
"emit-handled-generic", "emit-handled-generic",
GUINT_TO_POINTER (COMPLEX_SIGNAL_GENERIC), GUINT_TO_POINTER (COMPLEX_SIGNAL_GENERIC),
39600,
test_emission_handled_setup, test_emission_handled_setup,
test_emission_handled_init, test_emission_handled_init,
test_emission_run, test_emission_run,
@ -1531,6 +1536,7 @@ static PerformanceTest tests[] = {
{ {
"emit-handled-generic-empty", "emit-handled-generic-empty",
GUINT_TO_POINTER (COMPLEX_SIGNAL_GENERIC_EMPTY), GUINT_TO_POINTER (COMPLEX_SIGNAL_GENERIC_EMPTY),
70400,
test_emission_handled_setup, test_emission_handled_setup,
test_emission_handled_init, test_emission_handled_init,
test_emission_run, test_emission_run,
@ -1541,6 +1547,7 @@ static PerformanceTest tests[] = {
{ {
"emit-handled-args", "emit-handled-args",
GUINT_TO_POINTER (COMPLEX_SIGNAL_ARGS), GUINT_TO_POINTER (COMPLEX_SIGNAL_ARGS),
37800,
test_emission_handled_setup, test_emission_handled_setup,
test_emission_handled_init, test_emission_handled_init,
test_emission_run_args, test_emission_run_args,
@ -1551,6 +1558,7 @@ static PerformanceTest tests[] = {
{ {
"notify-unhandled", "notify-unhandled",
complex_object_get_type, complex_object_get_type,
526300,
test_notify_unhandled_setup, test_notify_unhandled_setup,
test_notify_unhandled_init, test_notify_unhandled_init,
test_notify_run, test_notify_run,
@ -1561,6 +1569,7 @@ static PerformanceTest tests[] = {
{ {
"notify-by-pspec-unhandled", "notify-by-pspec-unhandled",
complex_object_get_type, complex_object_get_type,
1568600,
test_notify_unhandled_setup, test_notify_unhandled_setup,
test_notify_unhandled_init, test_notify_unhandled_init,
test_notify_by_pspec_run, test_notify_by_pspec_run,
@ -1571,6 +1580,7 @@ static PerformanceTest tests[] = {
{ {
"notify-handled", "notify-handled",
complex_object_get_type, complex_object_get_type,
25500,
test_notify_handled_setup, test_notify_handled_setup,
test_notify_handled_init, test_notify_handled_init,
test_notify_run, test_notify_run,
@ -1581,6 +1591,7 @@ static PerformanceTest tests[] = {
{ {
"notify-by-pspec-handled", "notify-by-pspec-handled",
complex_object_get_type, complex_object_get_type,
26600,
test_notify_handled_setup, test_notify_handled_setup,
test_notify_handled_init, test_notify_handled_init,
test_notify_by_pspec_run, test_notify_by_pspec_run,
@ -1591,6 +1602,7 @@ static PerformanceTest tests[] = {
{ {
"property-set", "property-set",
complex_object_get_type, complex_object_get_type,
346300,
test_set_setup, test_set_setup,
test_set_init, test_set_init,
test_set_run, test_set_run,
@ -1601,6 +1613,7 @@ static PerformanceTest tests[] = {
{ {
"property-get", "property-get",
complex_object_get_type, complex_object_get_type,
329200,
test_get_setup, test_get_setup,
test_get_init, test_get_init,
test_get_run, test_get_run,
@ -1611,6 +1624,7 @@ static PerformanceTest tests[] = {
{ {
"refcount", "refcount",
NULL, NULL,
83000,
test_refcount_setup, test_refcount_setup,
test_refcount_init, test_refcount_init,
test_refcount_run, test_refcount_run,
@ -1621,6 +1635,7 @@ static PerformanceTest tests[] = {
{ {
"refcount-1", "refcount-1",
NULL, NULL,
230000,
test_refcount_setup, test_refcount_setup,
test_refcount_init, test_refcount_init,
test_refcount_1_run, test_refcount_1_run,
@ -1631,6 +1646,7 @@ static PerformanceTest tests[] = {
{ {
"refcount-toggle", "refcount-toggle",
NULL, NULL,
133000,
test_refcount_setup, test_refcount_setup,
test_refcount_init, test_refcount_init,
test_refcount_1_run, test_refcount_1_run,