After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 756316 - GSequence should provide fast api to check if empty
GSequence should provide fast api to check if empty
Status: RESOLVED FIXED
Product: glib
Classification: Platform
Component: general
unspecified
Other Linux
: Normal normal
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks:
 
 
Reported: 2015-10-09 20:09 UTC by Christian Hergert
Modified: 2015-10-15 19:55 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
O(1) implementation of g_sequence_is_empty() (3.12 KB, patch)
2015-10-09 20:37 UTC, Christian Hergert
none Details | Review
O(1) implementation of g_sequence_is_empty() (3.07 KB, patch)
2015-10-09 20:40 UTC, Christian Hergert
none Details | Review
O(1) implementation of g_sequence_is_empty() (3.01 KB, patch)
2015-10-09 20:42 UTC, Christian Hergert
none Details | Review
O(1) implementation of g_sequence_is_empty() (3.19 KB, patch)
2015-10-09 21:03 UTC, Christian Hergert
committed Details | Review

Description Christian Hergert 2015-10-09 20:09:10 UTC
Often I find myself adding short-circuits to avoid costly lookups (even when using GSequence). Especially when a GCompareFunc is expensive.

So people don't do the wrong thing here and call !g_sequence_get_length(), we should provide API that does the fast O(1) thing.

  if (g_sequence_get_begin_iter (seq) == g_sequence_get_end_iter (seq))

vs

  if (g_sequence_is_empty (seq))


While I generally don't advise using data-structures you don't understand the implementation of, i do think this makes the code more approachable to those not familiar with the implementation.

Willing to provide a quick patch if the suggestion isn't immediately nixed :)
Comment 1 Christian Hergert 2015-10-09 20:16:36 UTC
Aha, it turns out get_length() is actually faster than the comparison above, so that further shows how valuable this could be.

get_length() has a direct pointer to end iter, and then walks to the root (node->parent->parent, etc), which then has access to the number of nodes directly.

Compare to get_begin_iter() which has to walk to the root and then to the left.

So two things:

O(h) is the fastest we can do here, where h is the height of the tree.
We want to use !get_length() to do only half the work of comparing begin and end iters.
Comment 2 Christian Hergert 2015-10-09 20:18:32 UTC
And of course I'm dumb again. We can just check pointers on seq->end_node.
Comment 3 Dan Winship 2015-10-09 20:28:43 UTC
I think we should have such an API and we shouldn't let you write it ;-P
Comment 4 Christian Hergert 2015-10-09 20:37:50 UTC
Created attachment 312980 [details] [review]
O(1) implementation of g_sequence_is_empty()

agreed, but here is something.
Comment 5 Christian Hergert 2015-10-09 20:40:13 UTC
Created attachment 312981 [details] [review]
O(1) implementation of g_sequence_is_empty()

dont check right, we are the end iter.
Comment 6 Christian Hergert 2015-10-09 20:42:39 UTC
Created attachment 312982 [details] [review]
O(1) implementation of g_sequence_is_empty()

simplify test case

last update i swear ;)
Comment 7 Christian Hergert 2015-10-09 21:03:36 UTC
Created attachment 312984 [details] [review]
O(1) implementation of g_sequence_is_empty()

Jasper didn't like my copying of the previous gtk-doc (and he's right). So breaking my promise and updating again with slightly less insulting documentation.
Comment 8 Christian Hergert 2015-10-15 18:55:31 UTC
Anyone mind acking this? Seems like relatively easy verification.
Comment 9 Matthias Clasen 2015-10-15 19:48:20 UTC
Review of attachment 312984 [details] [review]:

Other than that cosmetic fix, looks good to me. Feel free to push with that cleanup

::: glib/tests/sequence.c
@@ +1364,3 @@
+
+  seq = g_sequence_new (NULL);
+  g_assert_cmpint (TRUE, ==, g_sequence_is_empty (seq));

Would be nicer to use g_assert_true and g_assert_false, instead of comparing booleans as integers