Буфер блокировки реализации MSVC istream - PullRequest
2 голосов
/ 28 апреля 2011

Я работаю с некоторым существующим кодом, который десериализует объекты, хранящиеся в текстовых файлах (мне потенциально нужно прочитать десятки миллионов из них). Содержимое файла сначала считывается в wstring, а затем из него получается wistringstream. Запуск профилировщика Very Sleepy в программе показывает, что он тратит около 20% своего времени на следующие стеки вызовов:

Mtxlock or RtlEnterCritialSection
std::_Mutex::_Lock
std::flush
std::basic_istream<wchar_t, std::char_traits<wchar_t> >::get
<rest of my program>

и аналогичные с std::_Mutex::_Unlock. Я использую Visual C ++ 2008.

Глядя на istream, я вижу, что он создает объект sentry, который вызывает _Lock и _Unlock методы для базового basic_streambuf. Это, в свою очередь, просто вызывает _Lock и _Unlock на _Mutex, связанном с этим буфером. Затем они определяются следующим образом:

#if _MULTI_THREAD
    // actually defines non-empty _Lock() and _Unlock() methods
#else /* _MULTI_THREAD */
    void _Lock()
    {   // do nothing
    }

void _Unlock()
    {   // do nothing
    }
#endif /* _MULTI_THREAD */

Похоже, _MULTI_THREAD установлен в yvals.h как

#define _MULTI_THREAD   1   /* nontrivial locks if multithreaded */

Теперь я знаю, что никогда не будет другого потока, пытающегося получить доступ к этому буферу, но мне кажется, что нет никакой возможности обойти эту блокировку при использовании стандартных iostreams, которые кажутся как странными, так и разочаровывающими. Я что-то пропустил? Есть ли обходной путь для этого?

Ответы [ 3 ]

1 голос
/ 28 апреля 2011

Проверьте значение библиотеки времени выполнения в свойствах проекта, C / C ++, генерация кода. Если он многопоточный, измените его на не многопоточную версию.

В любой версии после Visual C ++ 7.1 (!) Вам не повезло , поскольку она была удалена , и вы застряли с многопоточным CRT.

0 голосов
/ 29 апреля 2011

Получился прямой доступ к базовому буферу, заменив такие вещи, как

c = _text_in->get();

с такими вещами

c = _text_in->rdbuf()->sbumpc();

исправил проблему и значительно повысил производительность.

0 голосов
/ 29 апреля 2011

std::flush кажется бессмысленным в вашем случае.Я не вижу, как вы сбросите istream, поэтому я подозреваю, что это результат tie.Вы можете отменить привязку, т.е. позвонить по номеру tie(NULL) на свой wistringstream.Это также должно уменьшить количество принятых блокировок.

...