mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-10 03:16:17 +01:00
optimise bitlocks with new atomic operations
Add a performance test for bitlocks. Make use of the new g_atomic_int_{and,or} to avoid having to do the usual compare-and-exchange loop. On a test machine, the change increases performance from approximately 20 million uncontended acquire/releases per second to 31 million.
This commit is contained in:
parent
858a328792
commit
d09443fe20
@ -205,11 +205,12 @@ void
|
||||
g_bit_lock (volatile gint *address,
|
||||
gint lock_bit)
|
||||
{
|
||||
guint mask = 1u << lock_bit;
|
||||
guint v;
|
||||
|
||||
retry:
|
||||
v = g_atomic_int_get (address);
|
||||
if (v & (1u << lock_bit))
|
||||
v = g_atomic_int_or (address, mask);
|
||||
if (v & mask)
|
||||
/* already locked */
|
||||
{
|
||||
guint class = ((gsize) address) % G_N_ELEMENTS (g_bit_lock_contended);
|
||||
@ -220,9 +221,6 @@ g_bit_lock (volatile gint *address,
|
||||
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (!g_atomic_int_compare_and_exchange (address, v, v | (1u << lock_bit)))
|
||||
goto retry;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -250,18 +248,12 @@ gboolean
|
||||
g_bit_trylock (volatile gint *address,
|
||||
gint lock_bit)
|
||||
{
|
||||
guint mask = 1u << lock_bit;
|
||||
guint v;
|
||||
|
||||
retry:
|
||||
v = g_atomic_int_get (address);
|
||||
if (v & (1u << lock_bit))
|
||||
/* already locked */
|
||||
return FALSE;
|
||||
v = g_atomic_int_or (address, mask);
|
||||
|
||||
if (!g_atomic_int_compare_and_exchange (address, v, v | (1u << lock_bit)))
|
||||
goto retry;
|
||||
|
||||
return TRUE;
|
||||
return ~v & mask;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -284,12 +276,9 @@ g_bit_unlock (volatile gint *address,
|
||||
gint lock_bit)
|
||||
{
|
||||
guint class = ((gsize) address) % G_N_ELEMENTS (g_bit_lock_contended);
|
||||
guint v;
|
||||
guint mask = 1u << lock_bit;
|
||||
|
||||
retry:
|
||||
v = g_atomic_int_get (address);
|
||||
if (!g_atomic_int_compare_and_exchange (address, v, v & ~(1u << lock_bit)))
|
||||
goto retry;
|
||||
g_atomic_int_and (address, ~mask);
|
||||
|
||||
if (g_atomic_int_get (&g_bit_lock_contended[class]))
|
||||
g_futex_wake (address);
|
||||
|
@ -181,6 +181,9 @@ noinst_PROGRAMS += atomic
|
||||
atomic_CFLAGS = -Wstrict-aliasing=2 $(INCLUDES)
|
||||
atomic_LDADD = $(progs_ldadd)
|
||||
|
||||
TEST_PROGS += bitlock
|
||||
bitlock_LDADD = $(progs_ldadd)
|
||||
|
||||
# some testing of gtester funcitonality
|
||||
XMLLINT=xmllint
|
||||
gtester-xmllint-check: # check testreport xml with xmllint if present
|
||||
|
39
glib/tests/bitlock.c
Normal file
39
glib/tests/bitlock.c
Normal file
@ -0,0 +1,39 @@
|
||||
#include <glib.h>
|
||||
|
||||
#define ITERATIONS 100000000
|
||||
|
||||
static void
|
||||
test_bitlocks (void)
|
||||
{
|
||||
guint64 start = g_get_monotonic_time ();
|
||||
gint lock = 0;
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < ITERATIONS; i++)
|
||||
{
|
||||
g_bit_lock (&lock, 0);
|
||||
g_bit_unlock (&lock, 0);
|
||||
}
|
||||
|
||||
{
|
||||
gdouble elapsed;
|
||||
gdouble rate;
|
||||
|
||||
elapsed = g_get_monotonic_time () - start;
|
||||
elapsed /= 1000000;
|
||||
rate = ITERATIONS / elapsed;
|
||||
|
||||
g_test_maximized_result (rate, "iterations per second");
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
if (g_test_perf ())
|
||||
g_test_add_func ("/bitlock/performance/uncontended", test_bitlocks);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
Loading…
Reference in New Issue
Block a user