изолировать Луа от локали - PullRequest
2 голосов
/ 25 апреля 2011

Я рассматриваю возможность встраивания Lua в приложение C ++ (работает под FreeBSD 8.2).Но бенчмаркинг показал плохую производительность в некоторых случаях.В частности, когда Lua пытается преобразовать строки в числа и сравнивать строки, это становится медленнее и, что еще хуже, нарушает масштабируемость (8 ядер работают хуже, чем одно!).Теперь я думаю, что это локаль, потому что, когда я избегаю автоконвертации, все работает отлично.Но для реальной жизни мне понадобится сравнение строк и преобразование чисел.Как я могу:

  1. изолировать Lua от локали, т.е. убедиться, что ни одна из функций Lua не использует локаль косвенно.Например, я могу предоставить свои собственные функции преобразования и сравнения?

  2. или вообще отключить локаль.Я попытался setlocale (LC_ALL, "C"), все работает нормально (смена языка), но узкое место остается

Обновление:

, следуя предложению lhf, я прыгнул прямо в код библиотеки Lua.То, что я нашел, это десятки мест, где (официально) используются функции, зависящие от локали.Чтобы удалить их все, потребуется слишком много усилий, должен быть лучший способ.Я пытался измерить, какие из них не масштабируются.Я также добавил некоторые другие часто используемые функции, а также некоторые из моих собственных интересов (создание и уничтожение интерпретатора Lua, установка глобальной переменной и т. Д.).Результаты следуют.Правильный процент должен составлять 700%, то есть 7 потоков должны работать в 7 раз лучше, чем 1 поток:

           nop:  824%  (1:106867300/7:881101495)
    sprintf %f:   57%  (1:2093975/7:1203949)
 sprintf %.14g:   51%  (1:2503818/7:1278312)
sprintf %.14lf:   73%  (1:2134432/7:1576657)
   sprintf %lf:   64%  (1:2083480/7:1340885)
    sprintf %d:  601%  (1:6388005/7:38426161)
     sscanf %s:  181%  (1:8484822/7:15439285)
     sscanf %f:  712%  (1:3722659/7:26511335)
     lua_cycle:  677%  (1:113483/7:768936)
    set_global:  715%  (1:1506045/7:10780282)
set_get_global:  605%  (1:2814992/7:17044081)
       strcoll:  670%  (1:38361144/7:257300597)
        getenv:  681%  (1:8526168/7:58131030)
       isdigit:  695%  (1:106894420/7:743529202)
       isalpha:  662%  (1:80771002/7:535055196)
    isalpha(r):  638%  (1:78232353/7:499207555)
        strtol:  694%  (1:16865106/7:117208528)
        strtod:  749%  (1:16727244/7:125323881)
          time:  168%  (1:727666/7:1225499)
  gettimeofday:  162%  (1:727549/7:1183433)

цифры меняются от запуска к запуску, но большая картина остается последовательной: двойные преобразования sprintf работают хуже, чем на одиночныхнить.время и время получаются плохо.sscanf с% s также плохо масштабируется, что довольно удивительно, но в моем случае это не проблема.

Наконец-то, возможно, он вообще не был языковым стандартом.Я изменил преобразование Lua из sprintf в какой-то упрощенный код, созданный вручную, и пока все отлично работает.

Кстати, первый тест был запущен на рабочем столе linux и ничего странного не показал.Я был удивлен поведением FreeBSD.

1 Ответ

5 голосов
/ 25 апреля 2011

Чтобы избежать локали в сравнении строк, измените strcoll на strcmp в lvm.c.Чтобы избежать локали при преобразовании строки в число, измените определение lua_str2number в luaconf.h, чтобы избежать strtod.(Тем не менее, обратите внимание, что предоставление собственного strtod не является легкой задачей.) Вы также можете удалить trydecpoint в llex.c.

...