我正在处理一些现有代码,这些代码反序列化存储在文本文件中的对象(我可能需要阅读数千万个这些代码)。首先将文件的内容读入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 */
现在,我知道永远不会有另一个线程试图访问这个缓冲区,但是我觉得在使用标准的iostream时没有办法绕过这个锁定,这似乎既奇怪又令人沮丧。我错过了什么吗?有解决方法吗?
答案 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();
修复了问题并大大提升了性能。