MSVC istream实现锁定缓冲区

时间:2011-04-28 16:48:13

标签: c++ multithreading visual-c++ iostream istream

我正在处理一些现有代码,这些代码反序列化存储在文本文件中的对象(我可能需要阅读数千万个这些代码)。首先将文件的内容读入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上调用了_Unlockbasic_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 */

现在,我知道永远不会有另一个线程试图访问这个缓冲区,但是我觉得在使用标准的iostream时没有办法绕过这个锁定,这似乎既奇怪又令人沮丧。我错过了什么吗?有解决方法吗?

3 个答案:

答案 0 :(得分:1)

检查项目属性,C / C ++,代码生成中的运行时库的值。如果它是多线程的,请将其更改为非多线程版本。

在Visual C ++ 7.1(!)之后的任何版本中,你运气不好as it's been removed,而且你仍然坚持使用多线程CRT。

答案 1 :(得分:0)

std::flush在你的情况下似乎毫无意义。我无法看到你如何刷新istream,所以我怀疑这是tie的结果。您可能想取消绑定,即在tie(NULL)上拨打wistringstream。这也应该减少锁的数量。

答案 2 :(得分:0)

事实证明,通过替换

之类的东西直接访问底层缓冲区
c = _text_in->get();

有这样的事情

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

修复了问题并大大提升了性能。