[glib] optimise bitlocks with new atomic operations
- From: Ryan Lortie <ryanl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] optimise bitlocks with new atomic operations
- Date: Sat, 28 May 2011 21:38:41 +0000 (UTC)
commit d09443fe20753fc44afd6ac25463ac52861701cb
Author: Ryan Lortie <desrt desrt ca>
Date: Sat May 28 16:41:59 2011 -0400
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.
glib/gbitlock.c | 27 ++++++++-------------------
glib/tests/Makefile.am | 3 +++
glib/tests/bitlock.c | 39 +++++++++++++++++++++++++++++++++++++++
3 files changed, 50 insertions(+), 19 deletions(-)
---
diff --git a/glib/gbitlock.c b/glib/gbitlock.c
index 72e0d6e..4e91e9a 100644
--- a/glib/gbitlock.c
+++ b/glib/gbitlock.c
@@ -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;
-
- if (!g_atomic_int_compare_and_exchange (address, v, v | (1u << lock_bit)))
- goto retry;
+ v = g_atomic_int_or (address, mask);
- 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);
diff --git a/glib/tests/Makefile.am b/glib/tests/Makefile.am
index 29e706e..39816e5 100644
--- a/glib/tests/Makefile.am
+++ b/glib/tests/Makefile.am
@@ -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
diff --git a/glib/tests/bitlock.c b/glib/tests/bitlock.c
new file mode 100644
index 0000000..694fe6d
--- /dev/null
+++ b/glib/tests/bitlock.c
@@ -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 ();
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]