2

我正在处理一些现有代码,这些代码正在反序列化存储在文本文件中的对象(我可能需要阅读数千万个这些对象)。文件的内容首先被读入 a wstring,然后它wistringstream从中生成 a 。在程序上运行 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 时无法绕过此锁定,这看起来既奇怪又令人沮丧。我错过了什么吗?有解决方法吗?

4

3 回答 3

1

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

在 Visual C++ 7.1 (!) 之后的任何版本中,您都不走运,因为它已被删除,并且您被多线程 CRT 卡住了。

于 2011-04-28T17:42:29.250 回答
0

在你的情况下std::flush似乎毫无意义。我看不出你会如何冲洗 an istream,所以我怀疑这是 a 的结果tie。您可能想要解绑,即调用tie(NULL)您的wistringstream. 这也应该减少所占用的锁的数量。

于 2011-04-29T08:09:53.940 回答
0

结果是通过替换类似的东西直接访问底层缓冲区

c = _text_in->get();

像这样的事情

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

解决了问题并大大提高了性能。

于 2011-04-29T15:59:32.517 回答