Я диагностирую кросс-кейс в кросс-платформенном (Windows и Linux) приложении, где toupper существенно медленнее в Windows. Я предполагаю, что это то же самое для tolower.
Изначально я тестировал это с помощью простой программы на каждом из них без информации о локали, или даже включая заголовочный файл, и было очень мало разницы в производительности. Тест был миллион циклов итерации, вызывающий каждый символ для строки функции toupper().
После включения файла заголовка и включения строки ниже он намного медленнее и вызывает множество функций локали библиотеки времени выполнения MS C. Это прекрасно, но удар производительности очень плох. В Linux это никак не влияет на производительность.
setlocale(LC_ALL, ""); // system default locale
Если я устанавливаю следующее, он выполняется так же быстро, как linux, но, похоже, пропускает все языковые функции.
setlocale(LC_ALL, NULL); // should be interpreted as the same as below?
OR
setlocale(LC_ALL, "C");
Примечание: Visual Studio 2015 для Windows 10 g++ для Linux работает Cent OS
Попробовали настройки параметров голландского языка и тот же результат, медленный на Windows, не разница в скорости на Linux.
Я делаю что-то неправильно или есть ошибка с настройками языкового стандарта в Windows или это другой способ, которым Linux не делает то, что должен? Я не отлаживал приложение linux, поскольку я не так хорошо знаком с Linux, поэтому не знаю точно, что он делает внутри. Что я должен проверить после сортировки?
Код ниже для тестирования (Linux):
// C++ is only used for timing. The original program is in C.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <chrono>
#include <locale.h>
using namespace std::chrono;
void strToUpper(char *strVal);
int main()
{
typedef high_resolution_clock Clock;
high_resolution_clock::time_point t1 = Clock::now();
// set locale
//setlocale(LC_ALL,"nl_NL");
setlocale(LC_ALL,"en_US");
// testing string
char str[] = "the quick brown fox jumps over the lazy dog";
for (int i = 0; i < 1000000; i++)
{
strToUpper(str);
}
high_resolution_clock::time_point t2 = Clock::now();
duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
printf("chrono time %2.6f:\n",time_span.count());
}
void strToUpper(char *strVal)
{
unsigned char *t;
t = (unsigned char *)strVal;
while (*t)
{
*t = toupper(*t);
*t++;
}
}
Для окон изменить локальную информацию на:
// set locale
//setlocale(LC_ALL,"nld_nld");
setlocale(LC_ALL, "english_us");
Вы можете увидеть изменение локали из разделителя в завершенное время, полная остановка против запятой.
EDIT - данные профилирования
Как вы можете видеть, большую часть времени, проведенного в дочерних системных вызовах от _toupper_l.
Без информации о языковой настройке вызов toupper НЕ вызывает дочернего _toupper_l, что делает его очень быстрым.