Optimize gtk_css_selector_match_all
We are dealing with really short lists here. 95% are < 10 matches, and the longest I've been able to record was 19. So just do away with the hash table and do sorted insertion in the array directly.
This commit is contained in:
@ -140,9 +140,27 @@ gtk_css_selector_tree_get_matches (const GtkCssSelectorTree *tree)
|
|||||||
return (gpointer *) ((guint8 *)tree + tree->matches_offset);
|
return (gpointer *) ((guint8 *)tree + tree->matches_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
g_ptr_array_insert_sorted (GPtrArray *array,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
for (i = 0; i < array->len; i++)
|
||||||
|
{
|
||||||
|
if (data == array->pdata[i])
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (data < array->pdata[i])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_ptr_array_insert (array, i, data);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_css_selector_tree_found_match (const GtkCssSelectorTree *tree,
|
gtk_css_selector_tree_found_match (const GtkCssSelectorTree *tree,
|
||||||
GHashTable *res)
|
GPtrArray *array)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
gpointer *matches;
|
gpointer *matches;
|
||||||
@ -151,7 +169,7 @@ gtk_css_selector_tree_found_match (const GtkCssSelectorTree *tree,
|
|||||||
if (matches)
|
if (matches)
|
||||||
{
|
{
|
||||||
for (i = 0; matches[i] != NULL; i++)
|
for (i = 0; matches[i] != NULL; i++)
|
||||||
g_hash_table_insert (res, matches[i], matches[i]);
|
g_ptr_array_insert_sorted (array, matches[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1714,18 +1732,6 @@ gtk_css_selectors_skip_initial_selector (GtkCssSelector *selector, const GtkCssS
|
|||||||
return (GtkCssSelector *)gtk_css_selector_previous (selector);
|
return (GtkCssSelector *)gtk_css_selector_previous (selector);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
direct_ptr_compare (const void *_a, const void *_b)
|
|
||||||
{
|
|
||||||
gpointer *a = (gpointer *)_a;
|
|
||||||
gpointer *b = (gpointer *)_b;
|
|
||||||
if (*a < *b)
|
|
||||||
return -1;
|
|
||||||
else if (*a == *b)
|
|
||||||
return 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gtk_css_selector_tree_match_foreach (const GtkCssSelector *selector,
|
gtk_css_selector_tree_match_foreach (const GtkCssSelector *selector,
|
||||||
const GtkCssMatcher *matcher,
|
const GtkCssMatcher *matcher,
|
||||||
@ -1751,28 +1757,15 @@ GPtrArray *
|
|||||||
_gtk_css_selector_tree_match_all (const GtkCssSelectorTree *tree,
|
_gtk_css_selector_tree_match_all (const GtkCssSelectorTree *tree,
|
||||||
const GtkCssMatcher *matcher)
|
const GtkCssMatcher *matcher)
|
||||||
{
|
{
|
||||||
GHashTable *res;
|
|
||||||
GPtrArray *array;
|
GPtrArray *array;
|
||||||
GHashTableIter iter;
|
|
||||||
gpointer key;
|
|
||||||
|
|
||||||
update_type_references ();
|
update_type_references ();
|
||||||
|
|
||||||
res = g_hash_table_new (g_direct_hash, g_direct_equal);
|
array = g_ptr_array_sized_new (16);
|
||||||
|
|
||||||
for (; tree != NULL;
|
for (; tree != NULL;
|
||||||
tree = gtk_css_selector_tree_get_sibling (tree))
|
tree = gtk_css_selector_tree_get_sibling (tree))
|
||||||
gtk_css_selector_foreach (&tree->selector, matcher, gtk_css_selector_tree_match_foreach, res);
|
gtk_css_selector_foreach (&tree->selector, matcher, gtk_css_selector_tree_match_foreach, array);
|
||||||
|
|
||||||
array = g_ptr_array_sized_new (g_hash_table_size (res));
|
|
||||||
|
|
||||||
g_hash_table_iter_init (&iter, res);
|
|
||||||
while (g_hash_table_iter_next (&iter, &key, NULL))
|
|
||||||
g_ptr_array_add (array, key);
|
|
||||||
|
|
||||||
g_hash_table_destroy (res);
|
|
||||||
|
|
||||||
qsort (array->pdata, array->len, sizeof (gpointer), direct_ptr_compare);
|
|
||||||
|
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user