Go to the first, previous, next, last section, table of contents.


Optimization of the *gettext functions

At this point of the discussion we should talk about an advantage of the GNU gettext implementation. Some readers might have pointed out that an internationalized program might have a poor performance if some string has to be translated in an inner loop. While this is unavoidable when the string varies from one run of the loop to the other it is simply a waste of time when the string is always the same. Take the following example:

{
  while (...)
    {
      puts (gettext ("Hello world"));
    }
}

When the locale selection does not change between two runs the resulting string is always the same. One way to use this is:

{
  str = gettext ("Hello world");
  while (...)
    {
      puts (str);
    }
}

But this solution is not usable in all situation (e.g. when the locale selection changes) nor is it good readable.

The GNU C compiler, version 2.7 and above, provide another solution for this. To describe this we show here some lines of the `intl/libgettext.h' file. For an explanation of the expression command block see section `Statements and Declarations in Expressions' in The GNU CC Manual.

#  if defined __GNUC__ && __GNUC__ == 2 && __GNUC_MINOR__ >= 7
extern int _nl_msg_cat_cntr;
#   define	dcgettext(domainname, msgid, category)           \
  (__extension__                                                 \
   ({                                                            \
     char *result;                                               \
     if (__builtin_constant_p (msgid))                           \
       {                                                         \
         static char *__translation__;                           \
         static int __catalog_counter__;                         \
         if (! __translation__                                   \
             || __catalog_counter__ != _nl_msg_cat_cntr)         \
           {                                                     \
             __translation__ =                                   \
               dcgettext__ ((domainname), (msgid), (category));  \
             __catalog_counter__ = _nl_msg_cat_cntr;             \
           }                                                     \
         result = __translation__;                               \
       }                                                         \
     else                                                        \
       result = dcgettext__ ((domainname), (msgid), (category)); \
     result;                                                     \
    }))
#  endif

The interesting thing here is the __builtin_constant_p predicate. This is evaluated at compile time and so optimization can take place immediately. Here two cases are distinguished: the argument to gettext is not a constant value in which case simply the function dcgettext__ is called, the real implementation of the dcgettext function.

If the string argument is constant we can reuse the once gained translation when the locale selection has not changed. This is exactly what is done here. The _nl_msg_cat_cntr variable is defined in the `loadmsgcat.c' which is available in `libintl.a' and is changed whenever a new message catalog is loaded.


Go to the first, previous, next, last section, table of contents.