gvarianttype: reduce g_variant_type_equal() overhead

Previously, g_variant_type_equal() would walk the strings multiple times.
In debug builds, you initially have the type checks for validity. But
also you walk the string to determine its length only to memcmp it after.

Instead, this does the comparison while walking the string for length.
This commit is contained in:
Christian Hergert 2024-09-20 10:26:17 -07:00
parent 84b6f747cb
commit 9879b7152a
2 changed files with 69 additions and 17 deletions

View File

@ -0,0 +1,67 @@
/* gvarianttype-private.h
*
* Copyright © 2007, 2008 Ryan Lortie
* Copyright © 2009, 2010 Codethink Limited
* Copyright © 2024 Christian Hergert
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#pragma once
#include "gvarianttype.h"
G_BEGIN_DECLS
static inline gboolean
_g_variant_type_equal (const GVariantType *type1,
const GVariantType *type2)
{
const char *str1 = (const char *)type1;
const char *str2 = (const char *)type2;
gsize index = 0;
int brackets = 0;
if (str1 == str2)
return TRUE;
do
{
if (str1[index] != str2[index])
return FALSE;
while (str1[index] == 'a' || str1[index] == 'm')
{
index++;
if (str1[index] != str2[index])
return FALSE;
}
if (str1[index] == '(' || str1[index] == '{')
brackets++;
else if (str1[index] == ')' || str1[index] == '}')
brackets--;
index++;
}
while (brackets);
return TRUE;
}
G_END_DECLS

View File

@ -22,7 +22,7 @@
#include "config.h"
#include "gvarianttype.h"
#include "gvarianttype-private.h"
#include <glib/gtestutils.h>
#include <glib/gstrfuncs.h>
@ -817,25 +817,10 @@ gboolean
g_variant_type_equal (gconstpointer type1,
gconstpointer type2)
{
const gchar *string1, *string2;
gsize size1, size2;
g_return_val_if_fail (g_variant_type_check (type1), FALSE);
g_return_val_if_fail (g_variant_type_check (type2), FALSE);
if (type1 == type2)
return TRUE;
size1 = g_variant_type_get_string_length (type1);
size2 = g_variant_type_get_string_length (type2);
if (size1 != size2)
return FALSE;
string1 = g_variant_type_peek_string (type1);
string2 = g_variant_type_peek_string (type2);
return memcmp (string1, string2, size1) == 0;
return _g_variant_type_equal (type1, type2);
}
/**