Search code examples
c++clinuxreadlineglob

Why does the first call to readline() slow down all subsequent calls to fnmatch()?


The following program illustrates the issue:

Makefile:

CFLAGS = -O3 -std=c++0x
LDFLAGS = -lreadline

test: test.o
    g++ $(CFLAGS) $< $(LDFLAGS) -o $@

test.o: test.cpp Makefile
    g++ $(CFLAGS) -c $<

test.cpp:

#include <fnmatch.h>
#include <readline/readline.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>

static double time()
{
    timespec    ts;
    clock_gettime(CLOCK_REALTIME, &ts);
    return ts.tv_sec + (1e-9 * (double)ts.tv_nsec);
}


static void time_fnmatch()
{
    for (int i = 0; i < 2; i++)
    {
        double t = time();
        for (int i = 0; i < 1000000; i++)
        {
            fnmatch("*.o", "testfile", FNM_PERIOD);
        }
        fprintf(stderr, "%f\n", time()-t);
    }
}

int main()
{
    time_fnmatch();

    char *input = readline("> ");
    free(input);

    time_fnmatch();
}

Output:

0.045371
0.044537
> 
0.185246
0.181607

Before calling readline(), the fnmatch calls are about 4x faster. Although this performance difference is worrying, I'm most interested in finding out what exactly the readline() call might be doing to the program state that would have this effect on other library calls.


Solution

  • Just a guess: readline initialization probably calls setlocale.

    When a program starts up, it is in the C locale; a call to setlocale(LC_ALL, "") will enable the default locale, and these days, the default locale usually uses UTF-8, in which case many string operations become more complex. (Even just iterating over a string.)