我正在尝试加快在std::cout
上打印很多内容的多线程程序。大部分打印的东西都是由几个变量(字符串,数字等)拼凑而成的字符串。对std::cout
的访问受互斥量保护,以防止来自多个线程的打印输出以下列方式混合在一起:
{
std::lock_guard<std::mutex> lock(mutex);
std::cout << stringA << " 1 " << 5 << 'C' << std::endl;
}
测量表明,由于std::cout
似乎需要花费一些时间来处理大型而复杂的字符串,因此多个线程花费大量时间等待互斥体。
我的问题是:
从理论上讲,我可以通过在进入互斥锁之前将字符串组装成std::stringstream
,然后将已经组装好的字符串发送到std::cout
来减少锁争用吗?如:
{
std::stringstream ss;
ss << stringA << " 1 " << 5 << 'C' << std::endl;
std::lock_guard<std::mutex> lock(mutex);
std::cout << ss.str();
}
如果是,这是否可以进一步改善?
答案 0 :(得分:4)
从理论上讲,我可以通过在进入互斥锁之前将字符串组装到std :: stringstream中,然后将已经组装好的字符串发送到std :: cout来减少锁争用吗?
绝对。 operator<<
必须做一些工作来格式化传入的类型。将字符串组装成std::stringstream
意味着您要先完成所有工作,而只需要将组装后的字符串写出到{{1} },这意味着您在锁定下花费的时间更少。
但是,请注意std::cout
会按值返回ss.str()
。这意味着您正在关键区域内复制字符串。最好写std::string
并直接在std::cout << ss.rdbuf()
内写基础字符串。
除此之外,您将希望尽可能减少输出到std::stringstream
所花费的时间。如果您从不调用任何C stdio函数,则可能应该调用std::cout
将其组合在一起:
std::ios_base::sync_with_stdio(false)
答案 1 :(得分:1)
我将完全丢弃字符串流,而赞成std::string::append
和std::to_string
。流倾向于拖拽很多面向语言环境的东西,并使实现比原始字符串操作更重。我会这样:
std::string str;
str.append(stringA).append(" 1 ").append('C').append('\n');
std::cout << str;