最小化的boost ::精神编译时间 [英] Minimizing boost::spirit compile times

查看:170
本文介绍了最小化的boost ::精神编译时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

减少的boost ::精神的编译时间任何想法?

Any ideas for reducing boost::spirit compile time?

我刚刚移植柔性解析器来提振精神::。该EBNF有大约25规则。

I have just ported a flex parser to boost::spirit. The EBNF has about 25 rules.

结果运行良好,运行时性能优良。

The result runs well and the runtime performance is fine.

问题是,编译需要永远!它需要大约10分钟,需要的内存几乎是千兆字节。原始挠曲解析器在几秒钟内编译。

The problem is that compile takes for ever! It takes about ten minutes and requires almost a gigabyte of memory. The original flex parser compiled in a few seconds.

我使用升压版本1.44.0和Visual Studio 2008。

I am using boost version 1.44.0 and Visual Studio 2008.

在乔尔·古斯曼的文章最佳实践它说:

In Joel de Guzman's article 'Best Practices' it says

与复杂的定义规则元气大伤的编译器。我们已经看到
  是一百多人规则
  线长,走了几个
  分编译

Rules with complex definitions hurt the compiler badly. We’ve seen rules that are more than a hundred lines long and take a couple of minutes to compile

好吧,我没有接近这个长什么,但我仍然编译时间超过几分钟

Well I do not have anything near that long, but my compile still takes way more than a couple of minutes

下面是我的语法的最复杂的部分。它是对被分解成较小的部分,以某种方式的候选人?

Here is the most complex part of my grammar. Is it a candidate for being broken up into smaller parts, in some way?

    rule
        =   (   tok.if_ >> condition  >> tok.then_ >> *sequel  )                            [ bind( &cRuleKit::AddRule, &myRulekit ) ]
        |   (   tok.if_ >> condition  >> tok.and_ >> condition >> tok.then_ >> *sequel  )   [ bind( &cRuleKit::AddRule, &myRulekit ) ]
        ;

    condition
        =   ( tok.identifier >> tok.oper_ >> tok.value )                                    [ bind( &cRuleKit::AddCondition, &myRulekit, _pass, _1, _2, _3 ) ]
        |   ( tok.identifier >> tok.between_ >> tok.value >> "," >> tok.value )             [ bind( &cRuleKit::AddConditionBetween, &myRulekit, _pass, _1, _3, _4 ) ]
        ;

    sequel
        =   ( tok.priority_ >> tok.high_ )      [ bind( &cRuleKit::setPriority, &myRulekit, 3 ) ]
        |   ( tok.priority_  )                  [ bind( &cRuleKit::setPriority, &myRulekit, 2 ) ]
        |   ( tok.interval_ >> tok.value )      [ bind( &cRuleKit::setInterval, &myRulekit, _2 ) ]
        |   ( tok.mp3_ >> tok.identifier )      [ bind( &cRuleKit::setMP3, &myRulekit, _2 ) ]
        |   ( tok.disable_ )                    [ bind( &cRuleKit::setNextRuleEnable, &myRulekit, false ) ]
        ;


通过注释掉的语法部分,我发现了编译器花哪一部分时间最多。


By commenting out parts of the grammar, I discovered which part the compiler was spending most time with.

        set_reading
            =   tok.set_reading >> +attribute_reading
            ;

        attribute_reading
            =   ( tok.name_ >> tok.identifier )
                [
                                                bind( &cPackage::Add, &myReadings, _pass, _2 )
                ]
            |   ( tok.nmea_ >> tok.identifier )
                [
                                                bind( &cPackage::setNextNMEA, &myReadings, _2 )
                ]
            |   ( tok.column_ >> tok.integer )
                [
                                                bind( &cPackage::setNextColumn, &myReadings, _2 )
                ]
            |   ( tok.precision_ >> tok.value )
                [
                                                bind( &cPackage::setNextPrecision, &myReadings, _2 )
                ]
            |   ( tok.unit_ >> tok.identifier )
                [
                                                bind( &cPackage::setNextUnit, &myReadings, _2 )
                ]
            |   ( tok.value_ >> tok.identifier )
                [
                                                bind( &cPackage::setNextValue, &myReadings, _2 )
                ]
            |   ( tok.qualifier_ >> tok.identifier >> tok.qual_col_ >> tok.integer )
                [
                                                bind( &cPackage::setNextQualifier, &myReadings, _2, _4 )
                ]
            ;

我不会把它复杂,但可以肯定的是最长的规则。所以我想我会尝试分裂它,就像这样:

I wouldn't call it complex, but it is certainly the longest rule. So I thought I would try splitting it up, like this:

    set_reading
        =   tok.set_reading >> +attribute_reading
        ;

    attribute_reading
        =   attribute_reading_name
        |   attribute_reading_nmea
        |   attribute_reading_col
        |   attribute_reading_precision
        |   attribute_reading_unit
        |   attribute_reading_value
        |   attribute_reading_qualifier
        ;



    attribute_reading_name
        =   ( tok.name_ >> tok.identifier )     [ bind( &cPackage::Add, &myReadings, _pass, _2 ) ]
        ;
    attribute_reading_nmea
        =   ( tok.nmea_ >> tok.identifier )     [ bind( &cPackage::setNextNMEA, &myReadings, _2 ) ]
        ;
    attribute_reading_col
        =   ( tok.column_ >> tok.integer )      [ bind( &cPackage::setNextColumn, &myReadings, _2 ) ]
        ;
    attribute_reading_precision
        =   ( tok.precision_ >> tok.value )     [ bind( &cPackage::setNextPrecision, &myReadings, _2 ) ]
        ;
    attribute_reading_unit
        =   ( tok.unit_ >> tok.identifier )     [ bind( &cPackage::setNextUnit, &myReadings, _2 ) ]
        ;
    attribute_reading_value
        =   ( tok.value_ >> tok.identifier )    [ bind( &cPackage::setNextValue, &myReadings, _2 ) ]
        ;
    attribute_reading_qualifier
        =   ( tok.qualifier_ >> tok.identifier >> tok.qual_col_ >> tok.integer ) [ bind( &cPackage::setNextQualifier, &myReadings, _2, _4 ) ]

        ;

这从总编译时可以节省几分钟的时间!

This saves several minutes from the total compile time!!!

奇怪的是,峰值内存需求保持不变,它只是需要的时间更短。

Strangely, the peak memory requirement remains the same, it is just required for less time

所以,我觉得有点更希望我在学习的boost ::精神的一切努力都将是值得的。

So, I am feeling a bit more hopeful that all my efforts in learning boost::spirit are going to be worthwhile.

我不认为这是一个有点奇怪,编译器必须仔细所以用这种方式引导。我还以为现代编译器会注意到,这个规则只是一个独立的或规则列表中。

I do think it is a bit strange that the compiler needs to be so carefully guided in this way. I would have thought a modern compiler would have noticed that this rule was just a list of independent OR rules.

我花了七天学习的boost ::精神和柔性移植少,但现实世界中,解析器最好的部分。我的结论是,它的工作原理和code是非常优雅。不幸的是,通过简单地扩大教程示例code为实际的应用中使用天真负担过重很快编译器 - 采取编译内存和时间变得完全不切实际的。显然,有管理这个问题的技术,但他们需要我没有时间去学习神秘的知识。我想我会坚持弯曲,这可能是丑陋和老套,但相对简单,快如闪电。

I have spent the best part of seven days learning boost::spirit and porting a small, but real world, parser from flex. My conclusion is that it works and the code is very elegant. Unfortunately, naive use by simply expanding the tutorial example code for a real application quickly overburdens the compiler - memory and time taken for a compile becomes completely impractical. Apparently there are techniques for managing this problem but they require arcane knowledge which I do not have the time to learn. I guess I will stick to flex which may be ugly and old-fashioned but is relatively simple and lightning fast.

推荐答案

我要来的提振结论:精神,优雅的,因为它是不适合许多现实世界的分析问题,是由于冗长的编译一个可行的选择倍,即使是专家无法修复。

I have to come to the conclusion that boost:spirit, elegant as it is, is not a viable option for many real world parsing problems due to the lengthy compile times that even experts cannot fix.

这往往是最好坚持像弯曲,这可能是丑陋和老套,但相对简单,快如闪电。

It is often best to stick to something like flex, which may be ugly and old-fashioned, but is relatively simple and lightning fast.

由于我认为一个现实世界的问题在这里的例子是,弯曲编译在几秒钟解析器的最重要组成部分的铁路图,但升压:精神依然十分钟隆隆外出

As an example of what I consider a 'real world' problem here is the railroad diagram of the most important part of a parser that flex compiles in a couple of seconds, but boost:spirit is still chugging away on after ten minutes

这篇关于最小化的boost ::精神编译时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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