Compare commits

...

3 Commits

Author SHA1 Message Date
Matthias Clasen
c96495966e match_all: Only allocate an array when needed
My statistics show that more than half of all calls end up
with 0 matches, so we can avoid some overhead by not allocating
an array at all in this case.
2015-09-09 11:11:11 -04:00
Matthias Clasen
c4ccdd18c8 Handle match_all returning NULL
This is in preparation for not allocating an array at all if there
are no matches.
2015-09-09 11:11:03 -04:00
Matthias Clasen
e506341451 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.
2015-09-09 11:10:58 -04:00
2 changed files with 93 additions and 93 deletions

View File

@@ -1638,15 +1638,20 @@ verify_tree_get_change_results (GtkCssProvider *provider,
int i;
tree_rules = _gtk_css_selector_tree_match_all (provider->priv->tree, matcher);
verify_tree_match_results (provider, matcher, tree_rules);
for (i = tree_rules->len - 1; i >= 0; i--)
if (tree_rules)
{
GtkCssRuleset *ruleset;
verify_tree_match_results (provider, matcher, tree_rules);
ruleset = tree_rules->pdata[i];
for (i = tree_rules->len - 1; i >= 0; i--)
{
GtkCssRuleset *ruleset;
verify_change |= _gtk_css_selector_get_change (ruleset->selector);
ruleset = tree_rules->pdata[i];
verify_change |= _gtk_css_selector_get_change (ruleset->selector);
}
g_ptr_array_free (tree_rules, TRUE);
}
if (change != verify_change)
@@ -1671,8 +1676,6 @@ verify_tree_get_change_results (GtkCssProvider *provider,
g_warning (s->str);
g_string_free (s, TRUE);
}
g_ptr_array_free (tree_rules, TRUE);
}
#endif
}
@@ -1711,46 +1714,46 @@ gtk_css_provider_get_style_property (GtkStyleProvider *provider,
}
tree_rules = _gtk_css_selector_tree_match_all (priv->tree, &matcher);
verify_tree_match_results (css_provider, &matcher, tree_rules);
prop_name = g_strdup_printf ("-%s-%s",
g_type_name (pspec->owner_type),
pspec->name);
for (i = tree_rules->len - 1; i >= 0; i--)
if (tree_rules)
{
GtkCssRuleset *ruleset = tree_rules->pdata[i];
verify_tree_match_results (css_provider, &matcher, tree_rules);
if (ruleset->widget_style == NULL)
continue;
prop_name = g_strdup_printf ("-%s-%s",
g_type_name (pspec->owner_type),
pspec->name);
for (val = ruleset->widget_style; val != NULL; val = val->next)
{
if (strcmp (val->name, prop_name) == 0)
{
GtkCssScanner *scanner;
for (i = tree_rules->len - 1; i >= 0; i--)
{
GtkCssRuleset *ruleset = tree_rules->pdata[i];
scanner = gtk_css_scanner_new (css_provider,
NULL,
val->section,
val->section != NULL ? gtk_css_section_get_file (val->section) : NULL,
val->value);
if (ruleset->widget_style == NULL)
continue;
found = _gtk_css_style_funcs_parse_value (value,
scanner->parser);
for (val = ruleset->widget_style; val != NULL; val = val->next)
{
if (strcmp (val->name, prop_name) == 0)
{
GtkCssScanner *scanner;
gtk_css_scanner_destroy (scanner);
scanner = gtk_css_scanner_new (css_provider,
NULL,
val->section,
val->section != NULL ? gtk_css_section_get_file (val->section) : NULL,
val->value);
found = _gtk_css_style_funcs_parse_value (value, scanner->parser);
gtk_css_scanner_destroy (scanner);
break;
}
}
break;
}
}
if (found)
break;
}
if (found)
break;
g_free (prop_name);
g_ptr_array_free (tree_rules, TRUE);
}
g_free (prop_name);
g_ptr_array_free (tree_rules, TRUE);
gtk_widget_path_unref (path);
return found;
@@ -1797,39 +1800,42 @@ gtk_css_style_provider_lookup (GtkStyleProviderPrivate *provider,
priv = css_provider->priv;
tree_rules = _gtk_css_selector_tree_match_all (priv->tree, matcher);
verify_tree_match_results (css_provider, matcher, tree_rules);
for (i = tree_rules->len - 1; i >= 0; i--)
if (tree_rules)
{
ruleset = tree_rules->pdata[i];
verify_tree_match_results (css_provider, matcher, tree_rules);
if (ruleset->styles == NULL)
continue;
if (!_gtk_bitmask_intersects (_gtk_css_lookup_get_missing (lookup),
ruleset->set_styles))
continue;
for (j = 0; j < ruleset->n_styles; j++)
for (i = tree_rules->len - 1; i >= 0; i--)
{
GtkCssStyleProperty *prop = ruleset->styles[j].property;
guint id = _gtk_css_style_property_get_id (prop);
ruleset = tree_rules->pdata[i];
if (!_gtk_css_lookup_is_missing (lookup, id))
if (ruleset->styles == NULL)
continue;
_gtk_css_lookup_set (lookup,
id,
ruleset->styles[j].section,
ruleset->styles[j].value);
if (!_gtk_bitmask_intersects (_gtk_css_lookup_get_missing (lookup),
ruleset->set_styles))
continue;
for (j = 0; j < ruleset->n_styles; j++)
{
GtkCssStyleProperty *prop = ruleset->styles[j].property;
guint id = _gtk_css_style_property_get_id (prop);
if (!_gtk_css_lookup_is_missing (lookup, id))
continue;
_gtk_css_lookup_set (lookup,
id,
ruleset->styles[j].section,
ruleset->styles[j].value);
}
if (_gtk_bitmask_is_empty (_gtk_css_lookup_get_missing (lookup)))
break;
}
if (_gtk_bitmask_is_empty (_gtk_css_lookup_get_missing (lookup)))
break;
g_ptr_array_free (tree_rules, TRUE);
}
g_ptr_array_free (tree_rules, TRUE);
if (change)
{
GtkCssMatcher change_matcher;

View File

@@ -141,8 +141,26 @@ gtk_css_selector_tree_get_matches (const GtkCssSelectorTree *tree)
}
static void
gtk_css_selector_tree_found_match (const GtkCssSelectorTree *tree,
GHashTable *res)
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
gtk_css_selector_tree_found_match (const GtkCssSelectorTree *tree,
GPtrArray **array)
{
int i;
gpointer *matches;
@@ -150,8 +168,11 @@ gtk_css_selector_tree_found_match (const GtkCssSelectorTree *tree,
matches = gtk_css_selector_tree_get_matches (tree);
if (matches)
{
if (!*array)
*array = g_ptr_array_sized_new (16);
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 +1735,6 @@ gtk_css_selectors_skip_initial_selector (GtkCssSelector *selector, const GtkCssS
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
gtk_css_selector_tree_match_foreach (const GtkCssSelector *selector,
const GtkCssMatcher *matcher,
@@ -1751,28 +1760,13 @@ GPtrArray *
_gtk_css_selector_tree_match_all (const GtkCssSelectorTree *tree,
const GtkCssMatcher *matcher)
{
GHashTable *res;
GPtrArray *array;
GHashTableIter iter;
gpointer key;
GPtrArray *array = NULL;
update_type_references ();
res = g_hash_table_new (g_direct_hash, g_direct_equal);
for (; tree != NULL;
tree = gtk_css_selector_tree_get_sibling (tree))
gtk_css_selector_foreach (&tree->selector, matcher, gtk_css_selector_tree_match_foreach, res);
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);
gtk_css_selector_foreach (&tree->selector, matcher, gtk_css_selector_tree_match_foreach, &array);
return array;
}