1  /* Measure wcrtomb function.
       2     Copyright The GNU Toolchain Authors.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <array_length.h>
      20  #include <limits.h>
      21  #include <locale.h>
      22  #include <string.h>
      23  #include <wchar.h>
      24  
      25  #include "bench-timing.h"
      26  #include "json-lib.h"
      27  
      28  #define NITERS 100000
      29  
      30  struct test_inputs
      31  {
      32    const char *locale;
      33    const wchar_t *input_chars;
      34  };
      35  
      36  /* The inputs represent different types of characters, e.g. RTL, 1 byte, 2
      37     byte, 3 byte and 4 byte chars.  The exact number of inputs per locale
      38     doesn't really matter because we're not looking to compare performance
      39     between locales.  */
      40  struct test_inputs inputs[] =
      41  {
      42    /* RTL.  */
      43    {"ar_SA.UTF-8",
      44     L",-.،؟ـًُّ٠٢٣٤ءآأؤإئابةتثجحخدذرزسشصضطظعغفقكلمنهوىي"},
      45  
      46    /* Various mixes of 1 and 2 byte chars.  */
      47    {"cs_CZ.UTF-8",
      48     L",.aAábcCčdDďeEéÉěĚfFghHiIíJlLmMnNňŇoóÓpPqQrřsSšŠTťuUúÚůŮvVWxyýz"},
      49  
      50    {"el_GR.UTF-8",
      51     L",.αΑβγδΔεΕζηΗθΘιΙκΚλμΜνΝξοΟπΠρΡσΣςτυΥφΦχψω"},
      52  
      53    {"en_GB.UTF-8",
      54     L",.aAāĀæÆǽǣǢbcCċdDðÐeEēĒfFgGġhHiIīĪlLmMnNoōpPqQrsSTuUūŪvVwxyȝzþÞƿǷ"},
      55  
      56    {"fr_FR.UTF-8",
      57     L",.aAàâbcCçdDeEéèêëfFghHiIîïjlLmMnNoOôœpPqQrRsSTuUùûvVwxyz"},
      58  
      59    {"he_IL.UTF-8",
      60     L"',.ִאבגדהוזחטיכךלמםנןסעפףצץקרשת"},
      61  
      62    /* Devanagari, Japanese, 3-byte chars.  */
      63    {"hi_IN.UTF-8",
      64     L"(।ं०४५७अआइईउऎएओऔकखगघचछजञटडढणतथदधनपफ़बभमयरलवशषसहािीुूृेैोौ्"},
      65  
      66    {"ja_JP.UTF-8",
      67     L".ー0123456789あアいイうウえエおオかカがきキぎくクぐけケげこコごさサざ"},
      68  
      69    /* More mixtures of 1 and 2 byte chars.  */
      70    {"ru_RU.UTF-8",
      71     L",.аАбвВгдДеЕёЁжЖзЗийЙкКлЛмМнНоОпПрстТуУфФхХЦчшШщъыЫьэЭюЮя"},
      72  
      73    {"sr_RS.UTF-8",
      74     L",.aAbcCćčdDđĐeEfgGhHiIlLmMnNoOpPqQrsSšŠTuUvVxyzZž"},
      75  
      76    {"sv_SE.UTF-8",
      77     L",.aAåÅäÄæÆbBcCdDeEfFghHiIjlLmMnNoOöÖpPqQrsSTuUvVwxyz"},
      78  
      79    /* Chinese, 3-byte chars  */
      80    {"zh_CN.UTF-8",
      81     L"一七三下不与世両並中串主乱予事二五亡京人今仕付以任企伎会伸住佐体作使"},
      82  
      83    /* 4-byte chars, because smileys are the universal language and we want to
      84       ensure optimal performance with them 😊.  */
      85    {"en_US.UTF-8",
      86     L"😀😁😂😃😄😅😆😇😈😉😊😋😌😍😎😏😐😑😒😓😔😕😖😗😘😙😚😛😜😝😞😟😠😡"}
      87  };
      88  
      89  char buf[MB_LEN_MAX];
      90  size_t ret;
      91  
      92  int
      93  main (int argc, char **argv)
      94  {
      95    json_ctx_t json_ctx;
      96    json_init (&json_ctx, 0, stdout);
      97    json_document_begin (&json_ctx);
      98  
      99    json_attr_string (&json_ctx, "timing_type", TIMING_TYPE);
     100    json_attr_object_begin (&json_ctx, "functions");
     101    json_attr_object_begin (&json_ctx, "wcrtomb");
     102  
     103    for (size_t i = 0; i < array_length (inputs); i++)
     104      {
     105        json_attr_object_begin (&json_ctx, inputs[i].locale);
     106        setlocale (LC_ALL, inputs[i].locale);
     107  
     108        timing_t min = 0x7fffffffffffffff, max = 0, total = 0;
     109        const wchar_t *inp = inputs[i].input_chars;
     110        const size_t len = wcslen (inp);
     111        mbstate_t s;
     112  
     113        memset (&s, '\0', sizeof (s));
     114  
     115        for (size_t n = 0; n < NITERS; n++)
     116  	{
     117  	  timing_t start, end, elapsed;
     118  
     119  	  TIMING_NOW (start);
     120  	  for (size_t j = 0; j < len; j++)
     121  	    ret = wcrtomb (buf, inp[j], &s);
     122  	  TIMING_NOW (end);
     123  	  TIMING_DIFF (elapsed, start, end);
     124  	  if (min > elapsed)
     125  	    min = elapsed;
     126  	  if (max < elapsed)
     127  	    max = elapsed;
     128  	  TIMING_ACCUM (total, elapsed);
     129  	}
     130        json_attr_double (&json_ctx, "max", max);
     131        json_attr_double (&json_ctx, "min", min);
     132        json_attr_double (&json_ctx, "mean", total / NITERS);
     133        json_attr_object_end (&json_ctx);
     134      }
     135  
     136    json_attr_object_end (&json_ctx);
     137    json_attr_object_end (&json_ctx);
     138    json_document_end (&json_ctx);
     139  }