(root)/
glib-2.79.0/
glib/
tests/
utf8-performance.c
       1  /* GLIB - Library of useful routines for C programming
       2   *
       3   * Copyright (C) 2010 Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
       4   *
       5   * SPDX-License-Identifier: LGPL-2.1-or-later
       6   *
       7   * This library is free software; you can redistribute it and/or
       8   * modify it under the terms of the GNU Lesser General Public
       9   * License as published by the Free Software Foundation; either
      10   * version 2.1 of the License, or (at your option) any later version.
      11   *
      12   * This library is distributed in the hope that it will be useful,
      13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15   * Lesser General Public License for more details.
      16   *
      17   * You should have received a copy of the GNU Lesser General Public
      18   * License along with this library; if not, see <http://www.gnu.org/licenses/>.
      19   */
      20  
      21  #include <string.h>
      22  
      23  #include <glib.h>
      24  
      25  static guint num_iterations = 0;
      26  
      27  static const char str_ascii[] =
      28      "The quick brown fox jumps over the lazy dog";
      29  
      30  static const gchar str_latin1[] =
      31      "Zwölf Boxkämpfer jagen Viktor quer über den großen Sylter Deich";
      32  
      33  /* Energizing GOELRO-talk in Russian, used by KDE */
      34  static const char str_cyrillic[] =
      35      "Широкая электрификация южных губерний даст мощный толчок подъёму "
      36      "сельского хозяйства.";
      37  
      38  /* First sentence from the Wikipedia article:
      39   * http://zh.wikipedia.org/w/index.php?title=%E6%B1%89%E5%AD%97&oldid=13053137 */
      40  static const char str_han[] =
      41      "漢字,亦稱中文字、中国字,在台灣又被稱為國字,是漢字文化圈廣泛使用的一種文字,屬於表意文字的詞素音節文字";
      42  
      43  typedef int (* GrindFunc) (const char *, gsize);
      44  
      45  #define GRIND_LOOP_BEGIN                 \
      46    {                                      \
      47      guint i;                             \
      48      for (i = 0; i < num_iterations; i++)
      49  
      50  #define GRIND_LOOP_END \
      51    }
      52  
      53  static int
      54  grind_get_char (const char *str, gsize len)
      55  {
      56    gunichar acc = 0;
      57    GRIND_LOOP_BEGIN
      58      {
      59        const char *p = str;
      60        while (*p)
      61          {
      62            acc += g_utf8_get_char (p);
      63            p = g_utf8_next_char (p);
      64          }
      65      }
      66    GRIND_LOOP_END;
      67    return acc;
      68  }
      69  
      70  static int
      71  grind_get_char_validated (const char *str, gsize len)
      72  {
      73    gunichar acc = 0;
      74    GRIND_LOOP_BEGIN
      75      {
      76        const char *p = str;
      77        while (*p)
      78          {
      79            acc += g_utf8_get_char_validated (p, -1);
      80            p = g_utf8_next_char (p);
      81          }
      82      }
      83    GRIND_LOOP_END;
      84    return acc;
      85  }
      86  
      87  static int
      88  grind_utf8_to_ucs4 (const char *str, gsize len)
      89  {
      90    GRIND_LOOP_BEGIN
      91      {
      92        gunichar *ustr;
      93        ustr = g_utf8_to_ucs4 (str, -1, NULL, NULL, NULL);
      94        g_free (ustr);
      95      }
      96    GRIND_LOOP_END;
      97    return 0;
      98  }
      99  
     100  static int
     101  grind_get_char_backwards (const char *str, gsize len)
     102  {
     103    gunichar acc = 0;
     104    GRIND_LOOP_BEGIN
     105      {
     106        const char *p = str + len;
     107        do
     108  	{
     109  	  p = g_utf8_prev_char (p);
     110  	  acc += g_utf8_get_char (p);
     111          }
     112        while (p != str);
     113      }
     114    GRIND_LOOP_END;
     115    return acc;
     116  }
     117  
     118  static int
     119  grind_utf8_to_ucs4_sized (const char *str, gsize len)
     120  {
     121    GRIND_LOOP_BEGIN
     122      {
     123        gunichar *ustr;
     124        ustr = g_utf8_to_ucs4 (str, len, NULL, NULL, NULL);
     125        g_free (ustr);
     126      }
     127    GRIND_LOOP_END;
     128    return 0;
     129  }
     130  
     131  static int
     132  grind_utf8_to_ucs4_fast (const char *str, gsize len)
     133  {
     134    GRIND_LOOP_BEGIN
     135      {
     136        gunichar *ustr;
     137        ustr = g_utf8_to_ucs4_fast (str, -1, NULL);
     138        g_free (ustr);
     139      }
     140    GRIND_LOOP_END;
     141    return 0;
     142  }
     143  
     144  static int
     145  grind_utf8_to_ucs4_fast_sized (const char *str, gsize len)
     146  {
     147    GRIND_LOOP_BEGIN
     148      {
     149        gunichar *ustr;
     150        ustr = g_utf8_to_ucs4_fast (str, len, NULL);
     151        g_free (ustr);
     152      }
     153    GRIND_LOOP_END;
     154    return 0;
     155  }
     156  
     157  static int
     158  grind_utf8_validate (const char *str, gsize len)
     159  {
     160    GRIND_LOOP_BEGIN
     161      g_utf8_validate (str, -1, NULL);
     162    GRIND_LOOP_END;
     163    return 0;
     164  }
     165  
     166  static int
     167  grind_utf8_validate_sized (const char *str, gsize len)
     168  {
     169    GRIND_LOOP_BEGIN
     170      g_utf8_validate (str, len, NULL);
     171    GRIND_LOOP_END;
     172    return 0;
     173  }
     174  
     175  typedef struct _GrindData {
     176    GrindFunc func;
     177    const char *str;
     178  } GrindData;
     179  
     180  static void
     181  perform (gconstpointer data)
     182  {
     183    GrindData *gd = (GrindData *) data;
     184    GrindFunc grind_func = gd->func;
     185    const char *str = gd->str;
     186    gsize len;
     187    gulong bytes_ground;
     188    gdouble time_elapsed;
     189    gdouble result;
     190  
     191    len = strlen (str);
     192    bytes_ground = (gulong) len * num_iterations;
     193  
     194    g_test_timer_start ();
     195  
     196    grind_func (str, len);
     197  
     198    time_elapsed = g_test_timer_elapsed ();
     199  
     200    result = ((gdouble) bytes_ground / time_elapsed) * 1.0e-6;
     201  
     202    g_test_maximized_result (result, "%7.1f MB/s", result);
     203  
     204    g_slice_free (GrindData, gd);
     205  }
     206  
     207  static void
     208  add_cases(const char *path, GrindFunc func)
     209  {
     210  #define ADD_CASE(script)                              \
     211    G_STMT_START {                                      \
     212      GrindData *gd;                                    \
     213      gchar *full_path;                                 \
     214      gd = g_slice_new0(GrindData);                     \
     215      gd->func = func;                                  \
     216      gd->str = str_##script;                           \
     217      full_path = g_strdup_printf("%s/" #script, path); \
     218      g_test_add_data_func (full_path, gd, perform);    \
     219      g_free (full_path);                               \
     220    } G_STMT_END
     221  
     222    ADD_CASE(ascii);
     223    ADD_CASE(latin1);
     224    ADD_CASE(cyrillic);
     225    ADD_CASE(han);
     226  
     227  #undef ADD_CASE
     228  }
     229  
     230  int
     231  main (int argc, char **argv)
     232  {
     233    g_test_init (&argc, &argv, NULL);
     234  
     235    num_iterations = g_test_perf () ? 500000 : 1;
     236  
     237    add_cases ("/utf8/perf/get_char", grind_get_char);
     238    add_cases ("/utf8/perf/get_char-backwards", grind_get_char_backwards);
     239    add_cases ("/utf8/perf/get_char_validated", grind_get_char_validated);
     240    add_cases ("/utf8/perf/utf8_to_ucs4", grind_utf8_to_ucs4);
     241    add_cases ("/utf8/perf/utf8_to_ucs4-sized", grind_utf8_to_ucs4_sized);
     242    add_cases ("/utf8/perf/utf8_to_ucs4_fast", grind_utf8_to_ucs4_fast);
     243    add_cases ("/utf8/perf/utf8_to_ucs4_fast-sized", grind_utf8_to_ucs4_fast_sized);
     244    add_cases ("/utf8/perf/utf8_validate", grind_utf8_validate);
     245    add_cases ("/utf8/perf/utf8_validate-sized", grind_utf8_validate_sized);
     246  
     247    return g_test_run ();
     248  }