【问题标题】:Fast multi-replacement into string快速多替换成字符串
【发布时间】:2014-04-29 13:50:56
【问题描述】:

我有如下字符串:

{A}jahshs{b}jwuw{c}wuqjwhaha{d}{e}{f}jsj{g}

我需要用不同的字符串替换每个{x}。问题来了,因为这个过程将重复大约 1000 次/秒,所以我需要一种优化/快速的方法来做到这一点。

有什么想法吗?升级换代?升压格式?等等。

【问题讨论】:

  • std::string::replace,测量并证明它不够快?
  • 但是我应该为字符串中的每个 {x} 调用替换,大约 10。所以每秒替换 10x1000。
  • 没有什么能取代您的测试和测量。有很多变数。如果你写了一些代码,它仍然比你预期的慢,我们至少可以看看你的代码并讨论。

标签: c++ string boost replace


【解决方案1】:
  1. 预分配所有缓冲区

    ....

  2. 利润

哦,不要发送垃圾邮件。 5 10 分钟内的示例代码。

好的:也可以Live On Coliru

#include <string>
#include <sstream>
#include <boost/utility/string_ref.hpp>

template <typename Range>
int expand(Range const& /*key*/)
{
    return rand()%42; // todo lookup value with key (be sure to stay lean here)
}

#include <iostream>
int main()
{
    static const std::string msg_template = "{A}jahshs{b}jwuw{c}wuqjwhaha{d}{e}{f}jsj{g}\n";

    std::ostringstream builder;
    builder.str().reserve(1024); // reserve ample room, not crucial since we reuse it anyways

    for (size_t iterations = 1ul << 14; iterations; --iterations)
    {
        builder.str("");
        std::ostreambuf_iterator<char> out(builder);

        for(auto f(msg_template.begin()), l(msg_template.end()); f != l;)
        {
            switch(*f)
            {
                case '{' : 
                    {
                        auto s = ++f;
                        size_t n = 0;

                        while (f!=l && *f != '}')
                            ++f, ++n;

                        // key is [s,f] now
                        builder << expand(boost::string_ref(&*s, n));

                        if (f!=l)
                            ++f; // skip '}'
                    }
                    break;
                default:
                    *out++ = *f++;
            }
        }
        // to make it slow, uncomment:
        // std::cout << builder.str();
    }
}

这在我的系统上运行大约 0.239 秒。 大约 68k 扩展/秒 哎呀。在 release 构建中,它每秒进行 400 万次扩展。在 Coliru it reaches almost 1 million expansions/second

改进空间:

  • 您可以预先验证输入
  • 如果您知道参数键始终为 1 个字母,那么您只需将 string_ref 替换为 char,并且不循环查找 '}'
  • 您可以预先计算参数的索引并继续前进。这里的好处不是那么确定(顺序内存访问在某些处理器上非常好,而幼稚的方法可能更快)

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-18
  • 1970-01-01
  • 1970-01-01
  • 2019-04-19
  • 2014-12-13
  • 2016-05-08
相关资源
最近更新 更多