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:
Ryan Lortie 2011-05-28 16:41:59 -04:00
parent 858a328792
commit d09443fe20
3 changed files with 50 additions and 19 deletions

View File

@ -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);

View File

@ -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
View 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 ();
}