ExpressionEngine CMS
Open, Free, Amazing

Thread

This is an archived forum and the content is probably no longer relevant, but is provided here for posterity.

The active forums are here.

Aaron Fowler asks: WHY are simple and advanced conditionals parsed at different times?

October 14, 2010 11:51am

Subscribe [9]
  • #1 / Oct 14, 2010 11:51am

    Derek Jones

    7561 posts

    Quoting from the archived forum thread:

    One thing I’ve learned from my first year of EE development is that because of the parse order of advanced conditionals they usually cause more problems than they solve.  This is unfortunate, because advanced conditionals can make for much cleaner template code, and sometimes simple conditionals just won’t do.

    EE is the first program/framework/language I’ve used that treats advanced conditionals differently than simple conditionals.  I’m assuming there was a good reason for this design decision - does anyone have insight as to what that reason is?

    Thanks,
    Aaron

    There actually is a rhyme and reason to it, and it comes down to diminishing returns of using PHP to parse strings with pseudo-variables, and being able to anticipate all of the myriad of ways that one might employ a conditional.  The result is making the most common and most basic conditionals as performance friendly and “active” as possible, and allowing flexibility for other more powerful use with a passive approach to avoid performance problems or inaccurate conditionals.

    Simple conditionals are strings that can be easily parsed, and at a point in the application’s execution that it can know for a certainty that the values of the “variables” will be known.

    Advanced conditionals are those that have multiple conditions, contain tags, have variables provided by tags, etc. and have a higher cost to parse the string to identify if they are “ready” to be evaluated.  So rather than repeatedly running that expensive code at each step of the template parser to parse each individual conditional when it is ready to go, which would severely degrade performance, all “Advanced” conditionals are parsed at the end of template execution after all tags so that we are certain that any “variables” that might be used are available and have been replaced with the corresponding values.

  • #2 / Oct 14, 2010 11:56am

    Jacob Russell

    17 posts

    What constitutes a tag in this discussion?  Anything with curly braces?

  • #3 / Oct 14, 2010 12:02pm

    Derek Jones

    7561 posts

    What constitutes a tag in this discussion?  Anything with curly braces?

    As the code executes, a more accurate description really is any conditional that is comprised of multiple comparison operations or variables that are not “whitelisted” (that the template parser knows about and knows for a fact when they are available) will be parsed as an “advanced” conditional.

    If you have tags that you are executing conditionally and have any doubt as to whether or not it’s going to execute, check your template parsing log and it will reveal what’s happening behind the scenes even if that content becomes hidden.  And keep in mind that embedded templates are not parsed until after the current template is finished, which means that using embedded templates in those circumstances can actually improve performance if it is more likely that the conditional will evaluate false when that particular template is requested.

    e.g. if you have an expensive channel entries tag in an advanced conditional that is hidden more often than it is displayed to the user, moving that tag to an embedded template and keeping just the embed tag inside the advanced conditional will result in significant overall gains.

  • #4 / Oct 14, 2010 12:10pm

    Bjørn Børresen

    629 posts

    Thanks for trying to explain this, Derek. I still don’t get it though ..

    Take this simple example:

    {preload_replace:location="faq"}               
    {if embed:location == 'wiki' OR embed:location == 'forums'}
        
            // loads of heavy code here
            
    {/if}
    
    {if location == 'faq'}
            // do something else
    {/if}

    In the example above all code will be run, always (including the loads of heavy code). Is that neccessary? The “location” variable will always get its value before the template parser hits the conditional.

    If you use variables in conditionals like that - should it not always be the case that the variables used in the conditional are declared / get their value somewhere _outside_ the conditional?

  • #5 / Oct 14, 2010 12:16pm

    Derek Jones

    7561 posts

    The cost of parsing conditional strings with multiple comparison operators is very different from parsing single.

    {if embed:location == 'wiki'}

    Is much more straightforward than:

    {if embed:location == 'wiki' OR embed:location == 'forums'}

    This is PHP parsing text strings, not a compiled scripting language.  We have to first see if the string has an “OR”.  If it does, then we would have to parse that string, checking it for variables that we know the value of.  If the result of that parsing is discovering that the conditional is:

    {if 'wiki' == 'wiki' OR some_tag_variable == 'forums'}

    Then those cycles are completely wasted.  We have to wait anyway, and will have to parse that conditional again.  Even though it’s easy with our human eyes to see that every “variable” there is available or not, that’s not the case with how PHP sees things.

    You’ll often see me using “variables” in quotes, because of course a template is just a big text string, and none of it has any semantic value as far as PHP is concerned.  EE is providing semantic value by using PHP’s string and regular expression functions, and it’s simply not possible to account for everything without making an application that is slower than molasses.

  • #6 / Oct 14, 2010 12:33pm

    Kevin Smith

    4784 posts

    First off, thank you for not creating an application that parses everything to the degree that it’s slow as molasses. No doubt we’d be in an uproar about that if it were the case.

    That said, I think we’re all just a bit fuzzy on how conditional parsing works because the docs aren’t very clear. I’m sure there’s a list somewhere (and Low’s PDF handout from EECI2010 Europe is informative), but could we get a list of simple conditionals in the docs so we can be sure of the things that are parsed as simple?

    Also, here’s something I’m struggling with at the moment on a new site: I’m trying to parse and display different portions of a template based on the URI string. When the ‘profile’ template is called in the ‘members’ template group, if the URI is /members/profile, I want the user’s profile to display. If it’s /members/profile/edit, I want them to be able to edit it. I’m using eMarketSouth’s String to modify the title, but the problem I’m running into is this: EE parses all the String plugin tags (along with all plugin tags) inside {if segment_3 == 'whatever'} whether it’s evaluated as true or not. From Low’s PDF, it appears that segments are simple conditionals, so… why is this happening?

  • #7 / Oct 14, 2010 12:39pm

    airways

    154 posts

    ...keep in mind that embedded templates are not parsed until after the current template is finished…

    So that means that if the

    // loads of heavy code

    were simply changed to

    {embed="global/load_of_heavy_code"}

    the performance problem is solved? In other words, embeds happen after all conditionals, tags, and everything else?

  • #8 / Oct 14, 2010 12:42pm

    Kevin Smith

    4784 posts

    In other words, embeds happen after all conditionals, tags, and everything else?

    Almost. Take a look at Low’s PDF for parse order info. REALLY informative.

  • #9 / Oct 14, 2010 12:44pm

    Derek Jones

    7561 posts

    ...keep in mind that embedded templates are not parsed until after the current template is finished…

    So that means that if the

    // loads of heavy code

    were simply changed to

    {embed="global/load_of_heavy_code"}

    the performance problem is solved? In other words, embeds happen after all conditionals, tags, and everything else?

    Yep.  Global Template Variables are about the only thing parsed afterward, so that it’s only done once for all included templates on the request.  Granted, embedded templates bring their own expense to the party, since the template parsing logic runs again for each template, which is why I add the caveat that it needs to be balanced.  If the conditional is evaluating as TRUE 90% of the time, then using an embedded template will not give you any gains.

  • #10 / Oct 14, 2010 12:47pm

    airways

    154 posts

    Indeed that is very informative Kevin. Printed it out and posting it in my cube now.

    The bit that applies to my question specifically is:

    7.    Parse advanced conditionals
    8.    Process embedded templates
            Redirect
    9.    Parse User Defined global variables and others:

    Which means effectively - yes - an embed should solve this performance issue.

    If the conditional is evaluating as TRUE 90% of the time, then using an embedded template will not give you any gains.

    Ah yeah that makes sense. I’ll scribble a note somewhere. 😉

  • #11 / Oct 14, 2010 1:26pm

    Aaron Fowler

    113 posts

    So how are conditionals inside of modules, etc, parsed? If I have the following code:

    {exp:channel:entries ...}
      {if title == 'something'}
        do this…
      {/if}
    
      {if segment_2 == 'something'}
        do this…
      {/if}
    {/exp:channel:entries}

    Are these simple or advanced conditionals?  If advanced, does this mean that any conditional inside tags are advanced?

    Thanks,
    Aaron

  • #12 / Oct 14, 2010 1:31pm

    Derek Jones

    7561 posts

    That’s determined by the module, but in most cases, they are evaluated in the context of the module’s tag being processed, and not evaluated later.  In the case of simple segment, embed conditionals, etc., they are still parsed before any tags, so in your example, the segment_2 conditional would have been parsed by the template parser before the channel entries tag.

  • #13 / Oct 14, 2010 1:49pm

    Aaron Fowler

    113 posts

    Thanks, Derek. I understand all the decisions made for performance reasons. What I’m still not fully grasping is why, when conditionals inside of tags have their own parse order separate from the template parse order, simple/advanced conditionals outside of tags are parsed separately.  Why not just parse them both early? Outside of a module’s tag, I can’t think of an example when I would ever need late parsing for advanced conditionals.

    Can anyone enlighten me or give me a concrete example of how late parsing would be useful outside of module tags?

    Aaron

  • #14 / Oct 14, 2010 1:54pm

    Derek Jones

    7561 posts

    They’re not separate - if EE knows it can parse it (simple conditionals), they are evaluated right then, regardless of where they are.

    Can anyone enlighten me or give me a concrete example of how late parsing would be useful outside of module tags?

    Again, the location isn’t really relevant.  It’s easy to see for human eyes, and easy to comprehend for programmers, since in a compiled scripting language, syntax structures easily provide context of execution order.  But this is just a string - PHP cannot quickly see if a conditional is “inside” some other structure since those structures are also in reality artificial.  We’d be parsing strings with regular expressions for every possible way that they might be encountered.

  • #15 / Oct 14, 2010 2:14pm

    Kevin Smith

    4784 posts

    Derek, any thoughts on my post above about the segment conditional evaluating false and still processing the plugin tags inside it?

.(JavaScript must be enabled to view this email address)

ExpressionEngine News!

#eecms, #events, #releases