【问题标题】:MSVC istream implementation locking bufferMSVC istream 实现锁定缓冲区
【发布时间】:2011-08-14 21:28:47
【问题描述】:

我正在处理一些现有代码,这些代码正在反序列化存储在文本文件中的对象(我可能需要阅读数千万个这些对象)。首先将文件的内容读入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 对象,该对象在底层basic_streambuf 上调用_Lock_Unlock 方法。这反过来只需在与该缓冲区关联的_Mutex 上调用_Lock_Unlock。然后定义如下:

#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 时无法绕过此锁定,这看起来既奇怪又令人沮丧。我错过了什么吗?有解决办法吗?

【问题讨论】:

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


    【解决方案1】:

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

    在 Visual C++ 7.1 (!) 之后的任何版本中,您都不走运as it's been removed,并且您被多线程 CRT 卡住了。

    【讨论】:

    • 感谢您的回复。不幸的是,我无法更改项目的代码生成选项,因为这是一个更大的库的一部分,其中一些确实需要多线程运行时。
    • 我看到你在 VS2008 上。所以如果你想使用istream,那你就不走运了——对不起......
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

      c = _text_in->get();
      

      这样的事情

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

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

      【讨论】:

      • 如果您只需要未格式化的数据,那么您根本不需要创建 istream。您只需要创建 std::filebuf 对象。
      猜你喜欢
      • 1970-01-01
      • 2020-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-12
      相关资源
      最近更新 更多