静态正则表达式对象还是重要的?

时间:2015-08-28 13:15:02

标签: c++ regex

假设我有以下功能:

bool IsNumber(std::string const& str)
{
    return std::regex_match(str, std::regex{"\\d+"});
}

我正在构建std::regex每个电话。这样做会记录性能开销吗?如果改成static会不会更好,如下所示?

bool IsNumber(std::string const& str)
{
    static std::regex const number_regex{"\\d+"};
    return std::regex_match(str, number_regex);
}

或者这不重要吗?

1 个答案:

答案 0 :(得分:1)

编译器可能无法识别每次调用时std :: regex的构造是否相等(例如,构造函数可以访问静态/全局变量)。因此,安全的方法是在任何情况下构建它。另一方面,现在的编译器非常聪明,也许他会深深地解析构造函数,以便意识到它必须随着时间的推移而保持不变,从而优化出来。无论如何:简介它。例如制作一个循环并测量几千次调用的时间(std :: chrono)(至少按秒的顺序)。 -

我制作了一个非常简单的测试程序来描述它:

#include <stdio.h>
#include <regex>
#include <chrono>

bool IsNumberA( std::string const& str )
{
    return std::regex_match( str, std::regex { "\\d+" } );
}

static std::regex number_regex( "\\d+" );
bool IsNumberB( std::string const& str )
{
    return std::regex_match( str, number_regex );
}

void main()
{
    size_t count = 100000;

    std::vector<std::string> aRandomStrings;

    for( size_t i = 0; i < count; i++ )
        aRandomStrings.push_back((rand() % 2 == 0) ? "nonumberatall" : "3141592");

    auto time = std::chrono::system_clock::now();

    size_t numberCountA = 0;
    for( size_t i = 0; i < count; i++ )
        if( IsNumberA( aRandomStrings[i] ) )
            numberCountA++;

    auto takenTimeA = std::chrono::duration_cast<std::chrono::milliseconds>
        (std::chrono::system_clock::now() - time);
    time = std::chrono::system_clock::now();    // reset

    size_t numberCountB = 0;
    for( size_t i = 0; i < count; i++ )
        if( IsNumberB( aRandomStrings[i] ) )
            numberCountB++;

    auto takenTimeB = std::chrono::duration_cast<std::chrono::milliseconds>
        (std::chrono::system_clock::now() - time);

    printf( "took %d ms for A, %d ms for B\n", takenTimeA.count(), takenTimeB.count() );
}

<强>结果

我还没有进行优化编译它,只是为了看看编译器(msvc)是否足够智能。

A 6283ms,B 41ms

优化:268毫秒,B 85毫秒

使用预定义变量(B)时,我们可以清楚地看到性能的大幅提升。案例B中较慢的释放对我来说并不是很清楚,但时间尺度可能太低了。此外,随机生成器中可能还有很多未知的东西。