为什么我的简单cpp-netlib程序需要这么长的编译? [英] Why does my simple cpp-netlib program take so long to compile?

查看:300
本文介绍了为什么我的简单cpp-netlib程序需要这么长的编译?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近开始学习cpp-netlib,并测试一个netlibs示例程序。

  #include< boost / network /protocol/http/client.hpp> 
#include< iostream>
int main()
{
使用命名空间boost :: network;
http :: client client;
http :: client :: request request(http://www.boost.org);
request<<标题(Connection,close);
http :: client :: response response = client.get(request);
std :: cout<<体(响应)< std :: endl;
return 0;
}

经过多个小时的研究,我发现我需要使用正确的命令编译我的程序是

  clang ++ -std = c ++ 11 -I /usr/local/Cellar/openssl/1.0.2e / include test.cpp -L /usr/local/Cellar/openssl/1.0.2e/lib -lboost_system-mt -lboost_thread-mt -lcppnetlib-client-connections -lcppnetlib-uri -lcppnetlib-server-parsers -lssl -lcrypto 

这是一个链接到一个较旧的问题,我发布,详细说明了我是如何找到我需要的一切程序编译 cpp-Netlib with Boost Mac OSX seg fault当使用HTTP客户端主体时



我发现大约需要15秒来编译,并想知道是否有一个方法让我加快这个过程?编译这个代码真的很慢,或者链接器花费了大量的时间去获得所有这些库,如果是的话,我可以加快这个速度吗?

解决方案

我似乎记得cpp-netlib使用Spirit Qi语法进行URL解析,例如

  /uri/accessors.hpp 
network / uri / uri.ipp




在这种情况下,减速似乎是 accessors.hpp

$ b中的 key_value_sequence $ b

这些都是非常模板重,需要相当多的时间来编译,只依赖于编译器使用(MSVC是最糟糕的,在我的经验)。



您可以防止包含这些标题。至少只包括需要它的翻译单元( cpp s);不要让它陷入你的common头依赖。这意味着编译器必须在每次迭代时重新编译这些东西(即使使用预编译的头文件,代价可能会非常大)。






取决于您的编译器版本,这些可能有助于:




  • 禁用调试信息(-g0)

  • 优化大小(-Os)

  • 定义BOOST_SPIRIT_USE_PHOENIX_V3(默认自〜1.58)

  • 定义 FUSION_MAX_VECTOR_SIZE 到小数字(默认值:10)



真的,如果你使用c ++ 14能力的clang



至少替换这个Qi解析器:

  #include< boost / spirit / include / qi.hpp> 

// ...
命名空间详细信息{
template< typename Map>
struct key_value_sequence:spirit :: qi :: grammar< uri :: const_iterator,Map()> {
typedef typename Map :: key_type key_type;
typedef typename Map :: mapped_type mapped_type;
typedef std :: pair< key_type,mapped_type> pair_type;

key_value_sequence():key_value_sequence :: base_type(query){
query = pair>> *((spirit :: qi :: lit(';')|'&')>> pair);
pair = key>> - ('='>> value);
key =
spirit :: qi :: char _(a-zA-Z_)> * spirit :: qi :: char _( - +。〜a-zA-Z_0-9 /%);
value = + spirit :: qi :: char _( - +。〜a-zA-Z_0-9 /%);
}

spirit :: qi :: rule< uri :: const_iterator,Map()>查询
spirit :: qi :: rule< uri :: const_iterator,pair_type()>对;
spirit :: qi :: rule< uri :: const_iterator,key_type()>键;
spirit :: qi :: rule< uri :: const_iterator,mapped_type()>值;
};
} //命名空间详细信息

template< class Map>
inline Map& query_map(const uri& uri_,Map& map){
const uri :: string_type range = uri_.query
details :: key_value_sequence< Map>解析器
spirit :: qi :: parse(boost :: begin(range),boost :: end(range),parser,map);
return map;
}

使用此X3版本:

  #include< boost / spirit / home / x3.hpp> 

// ...
命名空间详细信息{
命名空间kvs_parser {
命名空间x3 = boost :: spirit :: x3;

static auto const key = x3 :: char _(a-zA-Z_)> * x3 :: char _( - +。〜a-zA-Z_0-9 /%);
static auto const value = + x3 :: char _( - +。〜a-zA-Z_0-9 /%);

template< typename Map,typename K = typename Map :: key_type,typename V = typename Map :: mapped_type,typename Pair = std :: pair< K,V& >
static auto const pair = x3 :: rule< struct kvs_pair,Pair> {}
= key>> - ('='>> value);

template< typename Map>
static auto const query = pair< Map> >> *((x3 :: lit(';')|'&')>> pair< Map>);
}
} //命名空间详细信息

template< class Map>
inline Map& query_map(const uri& uri_,Map& map){
const uri :: string_type range = uri_.query
spirit :: x3 :: parse(boost :: begin(range),boost :: end(range),details :: kvs_parser :: query< Map> map;
return map;
}

在我的系统上将编译时间从〜8s降低到〜5s



> 根据我的知识翻译成X3)



I recently started learning cpp-netlib and am testing out one of netlibs example programs

#include <boost/network/protocol/http/client.hpp>
#include <iostream>
int main()
{
    using namespace boost::network;
    http::client client;
    http::client::request request("http://www.boost.org");
    request << header("Connection", "close");
    http::client::response response = client.get(request);
    std::cout << body(response) << std::endl;
    return 0;
}

After many hours of research I found that the proper command I need to use to compile my program is

clang++ -std=c++11 -I /usr/local/Cellar/openssl/1.0.2e/include test.cpp -L /usr/local/Cellar/openssl/1.0.2e/lib -lboost_system-mt -lboost_thread-mt -lcppnetlib-client-connections -lcppnetlib-uri -lcppnetlib-server-parsers -lssl -lcrypto

Here is a link to an older question that I posted detailing how I came about finding everything I needed for this program to compile cpp-Netlib with Boost Mac OSX seg fault when using HTTP Client body

I find that it takes about 15 seconds to compile and was wondering if there was a way for me to speed up this process? Is it really this slow to compile this code or is the linker taking a good amount of time to go and get all these libraries and if so can I speed this up?

解决方案

I seem to remember cpp-netlib uses Spirit Qi grammarts for URL parsing e.g.

network/uri/accessors.hpp
network/uri/uri.ipp

In this case the slowdown seems to be the key_value_sequence parser in accessors.hpp

These are very template heavy and take considerable time to compile, depending only slightly on the compiler used (MSVC being worst, in my experience).

You could prevent inclusion of these headers. At the very least only include them in the translation units (cpps) that require it; don't ever make it get caught up in your "common" header dependencies. That would mean the compiler has to recompile that stuff on each iteration (even using precompiled headers the cost would likely be significant).


Depending on your compiler version, these could help:

  • disable debug information (-g0)
  • optimize for size (-Os)
  • define BOOST_SPIRIT_USE_PHOENIX_V3 (default since ~1.58)
  • define things like FUSION_MAX_VECTOR_SIZE to smaller numbers (default: 10)

Really, if you use c++14 capable clang, I'd be interested in testing a patch to use Spirit X3 instead of Qi.

At least replacing this Qi parser:

#include <boost/spirit/include/qi.hpp>

// ...
namespace details {
template <typename Map>
struct key_value_sequence : spirit::qi::grammar<uri::const_iterator, Map()> {
  typedef typename Map::key_type key_type;
  typedef typename Map::mapped_type mapped_type;
  typedef std::pair<key_type, mapped_type> pair_type;

  key_value_sequence() : key_value_sequence::base_type(query) {
    query = pair >> *((spirit::qi::lit(';') | '&') >> pair);
    pair = key >> -('=' >> value);
    key =
        spirit::qi::char_("a-zA-Z_") >> *spirit::qi::char_("-+.~a-zA-Z_0-9/%");
    value = +spirit::qi::char_("-+.~a-zA-Z_0-9/%");
  }

  spirit::qi::rule<uri::const_iterator, Map()> query;
  spirit::qi::rule<uri::const_iterator, pair_type()> pair;
  spirit::qi::rule<uri::const_iterator, key_type()> key;
  spirit::qi::rule<uri::const_iterator, mapped_type()> value;
};
}  // namespace details

template <class Map>
inline Map &query_map(const uri &uri_, Map &map) {
  const uri::string_type range = uri_.query();
  details::key_value_sequence<Map> parser;
  spirit::qi::parse(boost::begin(range), boost::end(range), parser, map);
  return map;
}

With this X3 variant:

#include <boost/spirit/home/x3.hpp>

// ...
namespace details {
    namespace kvs_parser {
        namespace x3 = boost::spirit::x3;

        static auto const key    = x3::char_("a-zA-Z_") >> *x3::char_("-+.~a-zA-Z_0-9/%");
        static auto const value  = +x3::char_("-+.~a-zA-Z_0-9/%");

        template <typename Map, typename K = typename Map::key_type, typename V = typename Map::mapped_type, typename Pair = std::pair<K, V> >
        static auto const pair   = x3::rule<struct kvs_pair, Pair> {} 
                                = key >> -('=' >> value);

        template <typename Map>
        static auto const query  = pair<Map> >> *((x3::lit(';') | '&') >> pair<Map>);
    }
}  // namespace details

template <class Map>
inline Map &query_map(const uri &uri_, Map &map) {
    const uri::string_type range = uri_.query();
    spirit::x3::parse(boost::begin(range), boost::end(range), details::kvs_parser::query<Map>, map);
    return map;
}

Reduces compilation time from ~8s down to ~5s on my system

BIG FAT WARNING The X3 code is untested (I don't even know what uses it, I just "blindly" translated to X3 to the best of my knowledge)

这篇关于为什么我的简单cpp-netlib程序需要这么长的编译?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆