For more information regarding the security incident at F5, the actions we are taking to address it, and our ongoing efforts to protect our customers, click here.

Forum Discussion

smp_86112's avatar
smp_86112
Icon for Cirrostratus rankCirrostratus
Jun 24, 2010

Optimizing If statement conditions

I see this examples like this all over the place:


when HTTP_REQUEST {
  if { [HTTP::host] equals "www.myhost.com" and [HTTP::uri] equals "/myuri" } {
    HTTP::redirect https://[HTTP::host][HTTP::uri]
  }
}

I am going though a large number of iRules in an attempt to optimize, and I had a thought occur to me while looking at one of mine like this. Shouldn't I be able to consolidate these two conditions into one, and wouldn't it be more efficient? Something like this?


when HTTP_REQUEST {
  if { [[HTTP::host][HTTP::uri]] equals "www.myhost.com/myuri" } { 
    HTTP::redirect https://[HTTP::host][HTTP::uri] 
  }
}

As a practical matter, this iRule generates an error when it is triggered:

TCL error: www.myhost.com - invalid command name "www.myhost.com/myuri" while executing "[HTTP::host][HTTP::uri]"

 

Assuming I can figure out how to properly write this condition (please help???), wouldn't this be more efficient than writing two conditions to evaluate and then compare? If I can get the syntax right, I'll test it out.

14 Replies

  • Another optimization technique that is often forgotten is to omit all code that always succeeds. If, for instance, the host on the virtual is always www.myhost.com (the virtual isn't multi-hosting domains), then leaving that check out completely wouldn't be a bad idea. In this case, it would be faster to build multiple iRules to run with different virtuals, than building a single iRule you could apply to mutliple virtuals. It would be more to maintain, but it would be faster.

     

     

    Good point for Jason on the "string tolower" checks. That is almost always done on the URI but isn't needed on the host header.

     

     

    -Joe

     

  • Yes, both Jason and hoolio bring up points I didn't consider. It seems this consolidation idea is only useful in pretty limited circumstances. Here are the results of my testing when forcing the string to lowercase (sorry for the long delay). It seems that adding the string tolower statement reversed the results. Does that make sense to you?

    
    timing on
    when HTTP_REQUEST {
      if { [string tolower [HTTP::host][HTTP::uri]] equals "www.myhost.com/admin" } {
        HTTP::uri "/new_uri"
      }
    }
    ltm rule-event  {
        aborts 0
        avg-cycles 14762
        event-type HTTP_REQUEST
        failures 0
        max-cycles 146684
        min-cycles 0
        name www.myhost.com
        priority 500
        total-executions 100017
    }
    ltm rule-event  {
        aborts 0
        avg-cycles 14892
        event-type HTTP_REQUEST
        failures 0
        max-cycles 121975
        min-cycles 0
        name www.myhost.com
        priority 500
        total-executions 100010
    }
    ltm rule-event  {
        aborts 0
        avg-cycles 14804
        event-type HTTP_REQUEST
        failures 0
        max-cycles 160099
        min-cycles 0
        name www.myhost.com
        priority 500
        total-executions 100014
    }
     
    timing on
    when HTTP_REQUEST {
      if { [HTTP::host] equals "www.myhost.com" and [string tolower [HTTP::uri]] equals "/admin" } {
        HTTP::uri "/new_uri"
      }
    }
    ltm rule-event  {
        aborts 0
        avg-cycles 14466
        event-type HTTP_REQUEST
        failures 0
        max-cycles 89955
        min-cycles 0
        name www.myhost.com
        priority 500
        total-executions 100014
    }
    ltm rule-event  {
        aborts 0
        avg-cycles 14457
        event-type HTTP_REQUEST
        failures 0
        max-cycles 129122
        min-cycles 0
        name www.myhost.com
        priority 500
        total-executions 100020
    }
    ltm rule-event  {
        aborts 0
        avg-cycles 14129
        event-type HTTP_REQUEST
        failures 0
        max-cycles 156109
        min-cycles 0
        name www.myhost.com
        priority 500
        total-executions 100021
    }
  • hoolio's avatar
    hoolio
    Icon for Cirrostratus rankCirrostratus
    I think that's just down to the extra few cycles it takes to handle a longer string that's being set to lower case:

     

     

    % set str ABCDEFGHIJKLMNOPQRSTABCDEFGHIJKLMN...

     

     

    % string length $str

     

    1000

     

     

    % time {string tolower $str} 1000

     

    79 microseconds per iteration

     

     

    % set smaller_str [string range $str 100 end]

     

     

    % time {string tolower $smaller_str} 1000

     

    65 microseconds per iteration/

     

     

    Though in theory you should set the Host value to lower case in order to check it. RFC2616 states that the Host evaluation must be done case-insensitively. In practice, I think all major browsers set the host to lowercase before sending the request anyhow.

     

     

    Aaron
  • You are absolutely right hoolio. I did the test again, this time setting the strings to lowercase in both conditions. It seems the consolidated statement is still faster, and the difference is a bit wider in this case. I won't post the whole thing anymore, just the avg-cycles:

    
    timing on
    when HTTP_REQUEST {
      if { [string tolower [HTTP::host][HTTP::uri]] equals "www.myhost.com/admin" } {
        HTTP::uri "/new_uri"
      }
    }
    avg-cycles 14762
    avg-cycles 14892
    avg-cycles 14804

    
    timing on
    when HTTP_REQUEST {
      if { [string tolower [HTTP::host]] equals "www.myhost.com" and [string tolower [HTTP::uri]] equals "/admin" } {
        HTTP::uri "/new_uri"
      }
    }
    avg-cycles 16219
    avg-cycles 16526
    avg-cycles 16626