Просматривая некоторые из наших журналов, я заметил в профилировщике, что мы тратили много времени в форматах operator<<
и т. Д. Похоже, что есть общая блокировка, которая используется всякий раз, когда ostream::operator<<
вызывается при форматировании int (и, вероятно, удваивается). После дальнейшего изучения я сузил его до этого примера:
Loop1, который использует ostringstream
для форматирования:
DWORD WINAPI doWork1(void* param)
{
int nTimes = *static_cast<int*>(param);
for (int i = 0; i < nTimes; ++i)
{
ostringstream out;
out << "[0";
for (int j = 1; j < 100; ++j)
out << ", " << j;
out << "]\n";
}
return 0;
}
Loop2, который использует тот же ostringstream
для всего, кроме формата int, что делается с itoa
:
DWORD WINAPI doWork2(void* param)
{
int nTimes = *static_cast<int*>(param);
for (int i = 0; i < nTimes; ++i)
{
ostringstream out;
char buffer[13];
out << "[0";
for (int j = 1; j < 100; ++j)
{
_itoa_s(j, buffer, 10);
out << ", " << buffer;
}
out << "]\n";
}
return 0;
}
Для моего теста я запускал каждый цикл несколько раз с 1, 2, 3 и 4 потоками (у меня 4-х ядерный компьютер). Количество испытаний является постоянным. Вот вывод:
doWork1: all ostringstream
n Total
1 557
2 8092
3 15916
4 15501
doWork2: use itoa
n Total
1 200
2 112
3 100
4 105
Как видите, производительность при использовании ostringstream ужасна. При добавлении потоков становится в 30 раз хуже, тогда как в Itoa это происходит в 2 раза быстрее.
Одной из идей является использование _configthreadlocale(_ENABLE_PER_THREAD_LOCALE)
в соответствии с рекомендацией M $ в этой статье . Это не помогает мне. Вот еще один пользователь , у которого, похоже, возникла похожая проблема.
Мы должны иметь возможность форматировать целые числа в нескольких потоках, работающих параллельно для нашего приложения. Учитывая эту проблему, нам нужно либо выяснить, как это сделать, либо найти другое решение для форматирования. Я могу написать простой класс с оператором <<, перегруженным для целочисленного и плавающего типов, а затем иметь шаблонную версию, которая просто вызывает оператор << в базовом потоке. Немного некрасиво, но я думаю, что смогу заставить это работать, хотя, возможно, не для определенного пользователем <code>operator<<(ostream&,T), потому что это не ostream
.
Я также должен прояснить, что это создается с помощью Microsoft Visual Studio 2005. И я считаю, что это ограничение связано с их реализацией стандартной библиотеки.