c++ stringstream 太慢,如何加速?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5830868/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 18:57:07  来源:igfitidea点击:

c++ stringstream is too slow, how to speed up?

c++performanceparsing

提问by hjbreg

Possible Duplicate:
Fastest way to read numerical values from text file in C++ (double in this case)

可能的重复:
从 C++ 中的文本文件读取数值的最快方法(在这种情况下为 double)

#include <ctime>
#include <cstdlib>
#include <string>
#include <sstream>
#include <iostream>
#include <limits>

using namespace std;

static const double NAN_D = numeric_limits<double>::quiet_NaN();

void die(const char *msg, const char *info)
{
    cerr << "** error: " << msg << " \"" << info << '\"';
    exit(1);
}

double str2dou1(const string &str)
{
    if (str.empty() || str[0]=='?') return NAN_D;
    const char *c_str = str.c_str();
    char *err;
    double x = strtod(c_str, &err);
    if (*err != 0) die("unrecognized numeric data", c_str);
    return x;
}

static istringstream string_to_type_stream;

double str2dou2(const string &str)
{
    if (str.empty() || str[0]=='?') return NAN_D;
    string_to_type_stream.clear();
    string_to_type_stream.str(str);
    double x = 0.0;
    if ((string_to_type_stream >> x).fail())
        die("unrecognized numeric data", str.c_str());
    return x;
}

int main()
{
    string str("12345.6789");

    clock_t tStart, tEnd;

    cout << "strtod: ";
    tStart=clock();

    for (int i=0; i<1000000; ++i)
        double x = str2dou1(str);

    tEnd=clock();
    cout << tEnd-tStart << endl;

    cout << "sstream: ";
    tStart=clock();

    for (int i=0; i<1000000; ++i)
        double x = str2dou2(str);

    tEnd=clock();
    cout << tEnd-tStart << endl;

    return 0;
}

strtod: 405
sstream: 1389

strtod:405 流
:1389

update: remove undersocres, env: win7+vc10

更新:删除下划线,环境:win7+vc10

回答by 6502

C/C++ text to number formatting is very slow. Streams are horribly slow but even C number parsing is slow because it's quite difficult to get it correct down to the last precision bit.

C/C++ 文本到数字格式非常慢。流非常慢,但即使是 C 数解析也很慢,因为很难将其准确到最后一个精度位。

In a production application where reading speed was important and where data was known to have at most three decimal digits and no scientific notation I got a vast improvement by hand-coding a floating parsing function handling only sign, integer part and any number of decimals (by "vast" I mean 10x faster compared to strtod).

在读取速度很重要并且已知数据最多具有三个十进制数字且没有科学记数法的生产应用程序中,我通过手动编码仅处理符号、整数部分和任意数量的小数的浮点解析函数获得了巨大的改进( “巨大”是指比 快 10 倍strtod)。

If you don't need exponent and the precision of this function is enough this is the code of a parser similar to the one I wrote back then. On my PC it's now 6.8 times faster than strtod and 22.6 times faster than sstream.

如果你不需要指数并且这个函数的精度足够了,那么这就是一个类似于我当时写的解析器的代码。在我的 PC 上,它现在比 strtod 快 6.8 倍,比 sstream 快 22.6 倍。

double parseFloat(const std::string& input)
{
    const char *p = input.c_str();
    if (!*p || *p == '?')
        return NAN_D;
    int s = 1;
    while (*p == ' ') p++;

    if (*p == '-') {
        s = -1; p++;
    }

    double acc = 0;
    while (*p >= '0' && *p <= '9')
        acc = acc * 10 + *p++ - '0';

    if (*p == '.') {
        double k = 0.1;
        p++;
        while (*p >= '0' && *p <= '9') {
            acc += (*p++ - '0') * k;
            k *= 0.1;
        }
    }
    if (*p) die("Invalid numeric format");
    return s * acc;
}

回答by 6502

string stream isslow. Quite very slow. If you are writing anything performance critical that acts on large data sets ( say loading assets after a level change during a game ) do not use string streams. I recommend using the old school c library parsing functions for performance, although I cannot say how they compare to something like boost spirit.

字符串流慢。相当非常缓慢。如果您正在编写任何对大型数据集起作用的关键性能(例如在游戏期间级别更改后加载资产),请不要使用字符串流。我建议使用老式的 c 库解析函数来提高性能,尽管我不能说它们与 boost Spirit 之类的东西相比如何。

However, compared to c library functions, string streams are very elegant, readable and reliable so if what you are doing is not performance ciritcal I recommend sticking to streams.

但是,与 c 库函数相比,字符串流非常优雅、可读和可靠,因此如果您所做的不是性能关键,我建议坚持使用流。

回答by Boaz Yaniv

In general, if you need speed, consider this library:

一般来说,如果你需要速度,可以考虑这个库:

http://www.fastformat.org/

http://www.fastformat.org/

(I'm not sure if it contains functions for converting strings or streams to other types, though, so it may not answer your current example).

(不过,我不确定它是否包含将字符串或流转换为其他类型的函数,因此它可能无法回答您当前的示例)。

For the record, please note you're comparing apples to oranges here. strtod()is a simple function that has a single purpose (converting strings to double), while stringstream is a much more complex formatting mechanism, which is far from being optimized to that specific purpose. A fairer comparison would be comparing stringstream to the sprintf/sscanf line of functions, which would be slower than strtod()but still faster than stringstream. I'm not exactly sure what makes stringstream's design slower than sprintf/sscanf, but it seems like that's the case.

作为记录,请注意您在此处将苹果与橙子进行比较。strtod()是一个具有单一目的的简单函数(将字符串转换为双精度),而 stringstream 是一种复杂得多的格式化机制,远未针对该特定目的进行优化。更公平的比较是将 stringstream 与 sprintf/sscanf 函数行进行比较,这strtod()将比 stringstream慢但仍比 stringstream 快。我不确定是什么让 stringstream 的设计比 sprintf/sscanf 慢,但似乎就是这种情况。

回答by ?imon Tóth

Have you considered using lexical_castfrom boost?

您是否考虑过使用lexical_castfrom boost?

http://www.boost.org/doc/libs/1_46_1/libs/conversion/lexical_cast.htm

http://www.boost.org/doc/libs/1_46_1/libs/conversion/lexical_cast.htm

Edit: btw, the clear()should be redundant.

编辑:顺便说一句,clear()应该是多余的。